cli-ih 0.6.3.1__py3-none-any.whl → 0.7.1__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 (427) hide show
  1. cli_ih/__init__.py +1 -0
  2. cli_ih/asyncClient.py +109 -10
  3. cli_ih/client.py +110 -18
  4. cli_ih/utils.py +51 -0
  5. cli_ih-0.7.1.dist-info/METADATA +100 -0
  6. cli_ih-0.7.1.dist-info/RECORD +9 -0
  7. {cli_ih-0.6.3.1.dist-info → cli_ih-0.7.1.dist-info}/top_level.txt +0 -1
  8. cli_ih-0.6.3.1.dist-info/METADATA +0 -86
  9. cli_ih-0.6.3.1.dist-info/RECORD +0 -425
  10. venv/Lib/site-packages/__editable___cli_ih_0_6_3_1_finder.py +0 -85
  11. venv/Lib/site-packages/pip/__init__.py +0 -13
  12. venv/Lib/site-packages/pip/__main__.py +0 -24
  13. venv/Lib/site-packages/pip/__pip-runner__.py +0 -50
  14. venv/Lib/site-packages/pip/_internal/__init__.py +0 -18
  15. venv/Lib/site-packages/pip/_internal/build_env.py +0 -349
  16. venv/Lib/site-packages/pip/_internal/cache.py +0 -291
  17. venv/Lib/site-packages/pip/_internal/cli/__init__.py +0 -3
  18. venv/Lib/site-packages/pip/_internal/cli/autocompletion.py +0 -184
  19. venv/Lib/site-packages/pip/_internal/cli/base_command.py +0 -244
  20. venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py +0 -1138
  21. venv/Lib/site-packages/pip/_internal/cli/command_context.py +0 -28
  22. venv/Lib/site-packages/pip/_internal/cli/index_command.py +0 -175
  23. venv/Lib/site-packages/pip/_internal/cli/main.py +0 -80
  24. venv/Lib/site-packages/pip/_internal/cli/main_parser.py +0 -134
  25. venv/Lib/site-packages/pip/_internal/cli/parser.py +0 -298
  26. venv/Lib/site-packages/pip/_internal/cli/progress_bars.py +0 -151
  27. venv/Lib/site-packages/pip/_internal/cli/req_command.py +0 -351
  28. venv/Lib/site-packages/pip/_internal/cli/spinners.py +0 -235
  29. venv/Lib/site-packages/pip/_internal/cli/status_codes.py +0 -6
  30. venv/Lib/site-packages/pip/_internal/commands/__init__.py +0 -139
  31. venv/Lib/site-packages/pip/_internal/commands/cache.py +0 -231
  32. venv/Lib/site-packages/pip/_internal/commands/check.py +0 -66
  33. venv/Lib/site-packages/pip/_internal/commands/completion.py +0 -135
  34. venv/Lib/site-packages/pip/_internal/commands/configuration.py +0 -288
  35. venv/Lib/site-packages/pip/_internal/commands/debug.py +0 -203
  36. venv/Lib/site-packages/pip/_internal/commands/download.py +0 -145
  37. venv/Lib/site-packages/pip/_internal/commands/freeze.py +0 -107
  38. venv/Lib/site-packages/pip/_internal/commands/hash.py +0 -58
  39. venv/Lib/site-packages/pip/_internal/commands/help.py +0 -40
  40. venv/Lib/site-packages/pip/_internal/commands/index.py +0 -159
  41. venv/Lib/site-packages/pip/_internal/commands/inspect.py +0 -92
  42. venv/Lib/site-packages/pip/_internal/commands/install.py +0 -798
  43. venv/Lib/site-packages/pip/_internal/commands/list.py +0 -400
  44. venv/Lib/site-packages/pip/_internal/commands/lock.py +0 -170
  45. venv/Lib/site-packages/pip/_internal/commands/search.py +0 -178
  46. venv/Lib/site-packages/pip/_internal/commands/show.py +0 -231
  47. venv/Lib/site-packages/pip/_internal/commands/uninstall.py +0 -113
  48. venv/Lib/site-packages/pip/_internal/commands/wheel.py +0 -181
  49. venv/Lib/site-packages/pip/_internal/configuration.py +0 -397
  50. venv/Lib/site-packages/pip/_internal/distributions/__init__.py +0 -21
  51. venv/Lib/site-packages/pip/_internal/distributions/base.py +0 -55
  52. venv/Lib/site-packages/pip/_internal/distributions/installed.py +0 -33
  53. venv/Lib/site-packages/pip/_internal/distributions/sdist.py +0 -165
  54. venv/Lib/site-packages/pip/_internal/distributions/wheel.py +0 -44
  55. venv/Lib/site-packages/pip/_internal/exceptions.py +0 -881
  56. venv/Lib/site-packages/pip/_internal/index/__init__.py +0 -1
  57. venv/Lib/site-packages/pip/_internal/index/collector.py +0 -489
  58. venv/Lib/site-packages/pip/_internal/index/package_finder.py +0 -1059
  59. venv/Lib/site-packages/pip/_internal/index/sources.py +0 -287
  60. venv/Lib/site-packages/pip/_internal/locations/__init__.py +0 -441
  61. venv/Lib/site-packages/pip/_internal/locations/_distutils.py +0 -173
  62. venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py +0 -215
  63. venv/Lib/site-packages/pip/_internal/locations/base.py +0 -82
  64. venv/Lib/site-packages/pip/_internal/main.py +0 -12
  65. venv/Lib/site-packages/pip/_internal/metadata/__init__.py +0 -164
  66. venv/Lib/site-packages/pip/_internal/metadata/_json.py +0 -87
  67. venv/Lib/site-packages/pip/_internal/metadata/base.py +0 -685
  68. venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py +0 -6
  69. venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py +0 -87
  70. venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +0 -223
  71. venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +0 -143
  72. venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py +0 -298
  73. venv/Lib/site-packages/pip/_internal/models/__init__.py +0 -1
  74. venv/Lib/site-packages/pip/_internal/models/candidate.py +0 -25
  75. venv/Lib/site-packages/pip/_internal/models/direct_url.py +0 -227
  76. venv/Lib/site-packages/pip/_internal/models/format_control.py +0 -78
  77. venv/Lib/site-packages/pip/_internal/models/index.py +0 -28
  78. venv/Lib/site-packages/pip/_internal/models/installation_report.py +0 -57
  79. venv/Lib/site-packages/pip/_internal/models/link.py +0 -613
  80. venv/Lib/site-packages/pip/_internal/models/pylock.py +0 -188
  81. venv/Lib/site-packages/pip/_internal/models/scheme.py +0 -25
  82. venv/Lib/site-packages/pip/_internal/models/search_scope.py +0 -126
  83. venv/Lib/site-packages/pip/_internal/models/selection_prefs.py +0 -53
  84. venv/Lib/site-packages/pip/_internal/models/target_python.py +0 -122
  85. venv/Lib/site-packages/pip/_internal/models/wheel.py +0 -141
  86. venv/Lib/site-packages/pip/_internal/network/__init__.py +0 -1
  87. venv/Lib/site-packages/pip/_internal/network/auth.py +0 -564
  88. venv/Lib/site-packages/pip/_internal/network/cache.py +0 -133
  89. venv/Lib/site-packages/pip/_internal/network/download.py +0 -342
  90. venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py +0 -213
  91. venv/Lib/site-packages/pip/_internal/network/session.py +0 -528
  92. venv/Lib/site-packages/pip/_internal/network/utils.py +0 -98
  93. venv/Lib/site-packages/pip/_internal/network/xmlrpc.py +0 -61
  94. venv/Lib/site-packages/pip/_internal/operations/__init__.py +0 -0
  95. venv/Lib/site-packages/pip/_internal/operations/build/__init__.py +0 -0
  96. venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py +0 -140
  97. venv/Lib/site-packages/pip/_internal/operations/build/metadata.py +0 -38
  98. venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py +0 -41
  99. venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py +0 -73
  100. venv/Lib/site-packages/pip/_internal/operations/build/wheel.py +0 -38
  101. venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py +0 -47
  102. venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py +0 -119
  103. venv/Lib/site-packages/pip/_internal/operations/check.py +0 -175
  104. venv/Lib/site-packages/pip/_internal/operations/freeze.py +0 -259
  105. venv/Lib/site-packages/pip/_internal/operations/install/__init__.py +0 -1
  106. venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py +0 -48
  107. venv/Lib/site-packages/pip/_internal/operations/install/wheel.py +0 -746
  108. venv/Lib/site-packages/pip/_internal/operations/prepare.py +0 -742
  109. venv/Lib/site-packages/pip/_internal/pyproject.py +0 -182
  110. venv/Lib/site-packages/pip/_internal/req/__init__.py +0 -105
  111. venv/Lib/site-packages/pip/_internal/req/constructors.py +0 -562
  112. venv/Lib/site-packages/pip/_internal/req/req_dependency_group.py +0 -75
  113. venv/Lib/site-packages/pip/_internal/req/req_file.py +0 -620
  114. venv/Lib/site-packages/pip/_internal/req/req_install.py +0 -937
  115. venv/Lib/site-packages/pip/_internal/req/req_set.py +0 -81
  116. venv/Lib/site-packages/pip/_internal/req/req_uninstall.py +0 -639
  117. venv/Lib/site-packages/pip/_internal/resolution/__init__.py +0 -0
  118. venv/Lib/site-packages/pip/_internal/resolution/base.py +0 -20
  119. venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py +0 -0
  120. venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +0 -598
  121. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py +0 -0
  122. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +0 -142
  123. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +0 -582
  124. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +0 -814
  125. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +0 -166
  126. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +0 -276
  127. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py +0 -85
  128. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py +0 -247
  129. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +0 -336
  130. venv/Lib/site-packages/pip/_internal/self_outdated_check.py +0 -254
  131. venv/Lib/site-packages/pip/_internal/utils/__init__.py +0 -0
  132. venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py +0 -109
  133. venv/Lib/site-packages/pip/_internal/utils/_log.py +0 -38
  134. venv/Lib/site-packages/pip/_internal/utils/appdirs.py +0 -52
  135. venv/Lib/site-packages/pip/_internal/utils/compat.py +0 -85
  136. venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py +0 -201
  137. venv/Lib/site-packages/pip/_internal/utils/datetime.py +0 -10
  138. venv/Lib/site-packages/pip/_internal/utils/deprecation.py +0 -126
  139. venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py +0 -87
  140. venv/Lib/site-packages/pip/_internal/utils/egg_link.py +0 -81
  141. venv/Lib/site-packages/pip/_internal/utils/entrypoints.py +0 -88
  142. venv/Lib/site-packages/pip/_internal/utils/filesystem.py +0 -152
  143. venv/Lib/site-packages/pip/_internal/utils/filetypes.py +0 -24
  144. venv/Lib/site-packages/pip/_internal/utils/glibc.py +0 -102
  145. venv/Lib/site-packages/pip/_internal/utils/hashes.py +0 -150
  146. venv/Lib/site-packages/pip/_internal/utils/logging.py +0 -364
  147. venv/Lib/site-packages/pip/_internal/utils/misc.py +0 -765
  148. venv/Lib/site-packages/pip/_internal/utils/packaging.py +0 -44
  149. venv/Lib/site-packages/pip/_internal/utils/retry.py +0 -45
  150. venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py +0 -149
  151. venv/Lib/site-packages/pip/_internal/utils/subprocess.py +0 -248
  152. venv/Lib/site-packages/pip/_internal/utils/temp_dir.py +0 -294
  153. venv/Lib/site-packages/pip/_internal/utils/unpacking.py +0 -337
  154. venv/Lib/site-packages/pip/_internal/utils/urls.py +0 -55
  155. venv/Lib/site-packages/pip/_internal/utils/virtualenv.py +0 -105
  156. venv/Lib/site-packages/pip/_internal/utils/wheel.py +0 -132
  157. venv/Lib/site-packages/pip/_internal/vcs/__init__.py +0 -15
  158. venv/Lib/site-packages/pip/_internal/vcs/bazaar.py +0 -130
  159. venv/Lib/site-packages/pip/_internal/vcs/git.py +0 -571
  160. venv/Lib/site-packages/pip/_internal/vcs/mercurial.py +0 -186
  161. venv/Lib/site-packages/pip/_internal/vcs/subversion.py +0 -335
  162. venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py +0 -693
  163. venv/Lib/site-packages/pip/_internal/wheel_builder.py +0 -334
  164. venv/Lib/site-packages/pip/_vendor/__init__.py +0 -117
  165. venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py +0 -29
  166. venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py +0 -70
  167. venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py +0 -168
  168. venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py +0 -75
  169. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +0 -8
  170. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +0 -145
  171. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +0 -48
  172. venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py +0 -511
  173. venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py +0 -119
  174. venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py +0 -157
  175. venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed +0 -0
  176. venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py +0 -146
  177. venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py +0 -43
  178. venv/Lib/site-packages/pip/_vendor/certifi/__init__.py +0 -4
  179. venv/Lib/site-packages/pip/_vendor/certifi/__main__.py +0 -12
  180. venv/Lib/site-packages/pip/_vendor/certifi/core.py +0 -83
  181. venv/Lib/site-packages/pip/_vendor/certifi/py.typed +0 -0
  182. venv/Lib/site-packages/pip/_vendor/dependency_groups/__init__.py +0 -13
  183. venv/Lib/site-packages/pip/_vendor/dependency_groups/__main__.py +0 -65
  184. venv/Lib/site-packages/pip/_vendor/dependency_groups/_implementation.py +0 -209
  185. venv/Lib/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py +0 -59
  186. venv/Lib/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py +0 -62
  187. venv/Lib/site-packages/pip/_vendor/dependency_groups/_toml_compat.py +0 -9
  188. venv/Lib/site-packages/pip/_vendor/dependency_groups/py.typed +0 -0
  189. venv/Lib/site-packages/pip/_vendor/distlib/__init__.py +0 -33
  190. venv/Lib/site-packages/pip/_vendor/distlib/compat.py +0 -1137
  191. venv/Lib/site-packages/pip/_vendor/distlib/resources.py +0 -358
  192. venv/Lib/site-packages/pip/_vendor/distlib/scripts.py +0 -447
  193. venv/Lib/site-packages/pip/_vendor/distlib/util.py +0 -1984
  194. venv/Lib/site-packages/pip/_vendor/distro/__init__.py +0 -54
  195. venv/Lib/site-packages/pip/_vendor/distro/__main__.py +0 -4
  196. venv/Lib/site-packages/pip/_vendor/distro/distro.py +0 -1403
  197. venv/Lib/site-packages/pip/_vendor/distro/py.typed +0 -0
  198. venv/Lib/site-packages/pip/_vendor/idna/__init__.py +0 -45
  199. venv/Lib/site-packages/pip/_vendor/idna/codec.py +0 -122
  200. venv/Lib/site-packages/pip/_vendor/idna/compat.py +0 -15
  201. venv/Lib/site-packages/pip/_vendor/idna/core.py +0 -437
  202. venv/Lib/site-packages/pip/_vendor/idna/idnadata.py +0 -4243
  203. venv/Lib/site-packages/pip/_vendor/idna/intranges.py +0 -57
  204. venv/Lib/site-packages/pip/_vendor/idna/package_data.py +0 -1
  205. venv/Lib/site-packages/pip/_vendor/idna/py.typed +0 -0
  206. venv/Lib/site-packages/pip/_vendor/idna/uts46data.py +0 -8681
  207. venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py +0 -55
  208. venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py +0 -48
  209. venv/Lib/site-packages/pip/_vendor/msgpack/ext.py +0 -170
  210. venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py +0 -929
  211. venv/Lib/site-packages/pip/_vendor/packaging/__init__.py +0 -15
  212. venv/Lib/site-packages/pip/_vendor/packaging/_elffile.py +0 -109
  213. venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py +0 -262
  214. venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py +0 -85
  215. venv/Lib/site-packages/pip/_vendor/packaging/_parser.py +0 -353
  216. venv/Lib/site-packages/pip/_vendor/packaging/_structures.py +0 -61
  217. venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py +0 -195
  218. venv/Lib/site-packages/pip/_vendor/packaging/licenses/__init__.py +0 -145
  219. venv/Lib/site-packages/pip/_vendor/packaging/licenses/_spdx.py +0 -759
  220. venv/Lib/site-packages/pip/_vendor/packaging/markers.py +0 -362
  221. venv/Lib/site-packages/pip/_vendor/packaging/metadata.py +0 -862
  222. venv/Lib/site-packages/pip/_vendor/packaging/py.typed +0 -0
  223. venv/Lib/site-packages/pip/_vendor/packaging/requirements.py +0 -91
  224. venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py +0 -1019
  225. venv/Lib/site-packages/pip/_vendor/packaging/tags.py +0 -656
  226. venv/Lib/site-packages/pip/_vendor/packaging/utils.py +0 -163
  227. venv/Lib/site-packages/pip/_vendor/packaging/version.py +0 -582
  228. venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py +0 -3676
  229. venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py +0 -631
  230. venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py +0 -55
  231. venv/Lib/site-packages/pip/_vendor/platformdirs/android.py +0 -249
  232. venv/Lib/site-packages/pip/_vendor/platformdirs/api.py +0 -299
  233. venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py +0 -144
  234. venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed +0 -0
  235. venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py +0 -272
  236. venv/Lib/site-packages/pip/_vendor/platformdirs/version.py +0 -21
  237. venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py +0 -272
  238. venv/Lib/site-packages/pip/_vendor/pygments/__init__.py +0 -82
  239. venv/Lib/site-packages/pip/_vendor/pygments/__main__.py +0 -17
  240. venv/Lib/site-packages/pip/_vendor/pygments/console.py +0 -70
  241. venv/Lib/site-packages/pip/_vendor/pygments/filter.py +0 -70
  242. venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py +0 -940
  243. venv/Lib/site-packages/pip/_vendor/pygments/formatter.py +0 -129
  244. venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py +0 -157
  245. venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py +0 -23
  246. venv/Lib/site-packages/pip/_vendor/pygments/lexer.py +0 -963
  247. venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +0 -362
  248. venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +0 -602
  249. venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +0 -1201
  250. venv/Lib/site-packages/pip/_vendor/pygments/modeline.py +0 -43
  251. venv/Lib/site-packages/pip/_vendor/pygments/plugin.py +0 -72
  252. venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py +0 -91
  253. venv/Lib/site-packages/pip/_vendor/pygments/scanner.py +0 -104
  254. venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +0 -247
  255. venv/Lib/site-packages/pip/_vendor/pygments/style.py +0 -203
  256. venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +0 -61
  257. venv/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py +0 -54
  258. venv/Lib/site-packages/pip/_vendor/pygments/token.py +0 -214
  259. venv/Lib/site-packages/pip/_vendor/pygments/unistring.py +0 -153
  260. venv/Lib/site-packages/pip/_vendor/pygments/util.py +0 -324
  261. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py +0 -31
  262. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py +0 -410
  263. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py +0 -21
  264. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py +0 -389
  265. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/py.typed +0 -0
  266. venv/Lib/site-packages/pip/_vendor/requests/__init__.py +0 -179
  267. venv/Lib/site-packages/pip/_vendor/requests/__version__.py +0 -14
  268. venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py +0 -50
  269. venv/Lib/site-packages/pip/_vendor/requests/adapters.py +0 -719
  270. venv/Lib/site-packages/pip/_vendor/requests/api.py +0 -157
  271. venv/Lib/site-packages/pip/_vendor/requests/auth.py +0 -314
  272. venv/Lib/site-packages/pip/_vendor/requests/certs.py +0 -17
  273. venv/Lib/site-packages/pip/_vendor/requests/compat.py +0 -90
  274. venv/Lib/site-packages/pip/_vendor/requests/cookies.py +0 -561
  275. venv/Lib/site-packages/pip/_vendor/requests/exceptions.py +0 -151
  276. venv/Lib/site-packages/pip/_vendor/requests/help.py +0 -127
  277. venv/Lib/site-packages/pip/_vendor/requests/hooks.py +0 -33
  278. venv/Lib/site-packages/pip/_vendor/requests/models.py +0 -1039
  279. venv/Lib/site-packages/pip/_vendor/requests/packages.py +0 -25
  280. venv/Lib/site-packages/pip/_vendor/requests/sessions.py +0 -831
  281. venv/Lib/site-packages/pip/_vendor/requests/status_codes.py +0 -128
  282. venv/Lib/site-packages/pip/_vendor/requests/structures.py +0 -99
  283. venv/Lib/site-packages/pip/_vendor/requests/utils.py +0 -1086
  284. venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py +0 -27
  285. venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py +0 -196
  286. venv/Lib/site-packages/pip/_vendor/resolvelib/py.typed +0 -0
  287. venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py +0 -55
  288. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers/__init__.py +0 -27
  289. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers/abstract.py +0 -47
  290. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers/criterion.py +0 -48
  291. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers/exceptions.py +0 -57
  292. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers/resolution.py +0 -622
  293. venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py +0 -209
  294. venv/Lib/site-packages/pip/_vendor/rich/__init__.py +0 -177
  295. venv/Lib/site-packages/pip/_vendor/rich/__main__.py +0 -245
  296. venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py +0 -454
  297. venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py +0 -3610
  298. venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py +0 -32
  299. venv/Lib/site-packages/pip/_vendor/rich/_export_format.py +0 -76
  300. venv/Lib/site-packages/pip/_vendor/rich/_extension.py +0 -10
  301. venv/Lib/site-packages/pip/_vendor/rich/_fileno.py +0 -24
  302. venv/Lib/site-packages/pip/_vendor/rich/_inspect.py +0 -268
  303. venv/Lib/site-packages/pip/_vendor/rich/_log_render.py +0 -94
  304. venv/Lib/site-packages/pip/_vendor/rich/_loop.py +0 -43
  305. venv/Lib/site-packages/pip/_vendor/rich/_null_file.py +0 -69
  306. venv/Lib/site-packages/pip/_vendor/rich/_palettes.py +0 -309
  307. venv/Lib/site-packages/pip/_vendor/rich/_pick.py +0 -17
  308. venv/Lib/site-packages/pip/_vendor/rich/_ratio.py +0 -153
  309. venv/Lib/site-packages/pip/_vendor/rich/_spinners.py +0 -482
  310. venv/Lib/site-packages/pip/_vendor/rich/_stack.py +0 -16
  311. venv/Lib/site-packages/pip/_vendor/rich/_timer.py +0 -19
  312. venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py +0 -661
  313. venv/Lib/site-packages/pip/_vendor/rich/_windows.py +0 -71
  314. venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py +0 -56
  315. venv/Lib/site-packages/pip/_vendor/rich/_wrap.py +0 -93
  316. venv/Lib/site-packages/pip/_vendor/rich/abc.py +0 -33
  317. venv/Lib/site-packages/pip/_vendor/rich/align.py +0 -306
  318. venv/Lib/site-packages/pip/_vendor/rich/ansi.py +0 -241
  319. venv/Lib/site-packages/pip/_vendor/rich/bar.py +0 -93
  320. venv/Lib/site-packages/pip/_vendor/rich/box.py +0 -474
  321. venv/Lib/site-packages/pip/_vendor/rich/cells.py +0 -174
  322. venv/Lib/site-packages/pip/_vendor/rich/color.py +0 -621
  323. venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py +0 -38
  324. venv/Lib/site-packages/pip/_vendor/rich/columns.py +0 -187
  325. venv/Lib/site-packages/pip/_vendor/rich/console.py +0 -2680
  326. venv/Lib/site-packages/pip/_vendor/rich/constrain.py +0 -37
  327. venv/Lib/site-packages/pip/_vendor/rich/containers.py +0 -167
  328. venv/Lib/site-packages/pip/_vendor/rich/control.py +0 -219
  329. venv/Lib/site-packages/pip/_vendor/rich/default_styles.py +0 -193
  330. venv/Lib/site-packages/pip/_vendor/rich/diagnose.py +0 -39
  331. venv/Lib/site-packages/pip/_vendor/rich/emoji.py +0 -91
  332. venv/Lib/site-packages/pip/_vendor/rich/errors.py +0 -34
  333. venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py +0 -57
  334. venv/Lib/site-packages/pip/_vendor/rich/filesize.py +0 -88
  335. venv/Lib/site-packages/pip/_vendor/rich/highlighter.py +0 -232
  336. venv/Lib/site-packages/pip/_vendor/rich/json.py +0 -139
  337. venv/Lib/site-packages/pip/_vendor/rich/jupyter.py +0 -101
  338. venv/Lib/site-packages/pip/_vendor/rich/layout.py +0 -442
  339. venv/Lib/site-packages/pip/_vendor/rich/live.py +0 -400
  340. venv/Lib/site-packages/pip/_vendor/rich/live_render.py +0 -106
  341. venv/Lib/site-packages/pip/_vendor/rich/logging.py +0 -297
  342. venv/Lib/site-packages/pip/_vendor/rich/markup.py +0 -251
  343. venv/Lib/site-packages/pip/_vendor/rich/measure.py +0 -151
  344. venv/Lib/site-packages/pip/_vendor/rich/padding.py +0 -141
  345. venv/Lib/site-packages/pip/_vendor/rich/pager.py +0 -34
  346. venv/Lib/site-packages/pip/_vendor/rich/palette.py +0 -100
  347. venv/Lib/site-packages/pip/_vendor/rich/panel.py +0 -317
  348. venv/Lib/site-packages/pip/_vendor/rich/pretty.py +0 -1016
  349. venv/Lib/site-packages/pip/_vendor/rich/progress.py +0 -1715
  350. venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py +0 -223
  351. venv/Lib/site-packages/pip/_vendor/rich/prompt.py +0 -400
  352. venv/Lib/site-packages/pip/_vendor/rich/protocol.py +0 -42
  353. venv/Lib/site-packages/pip/_vendor/rich/py.typed +0 -0
  354. venv/Lib/site-packages/pip/_vendor/rich/region.py +0 -10
  355. venv/Lib/site-packages/pip/_vendor/rich/repr.py +0 -149
  356. venv/Lib/site-packages/pip/_vendor/rich/rule.py +0 -130
  357. venv/Lib/site-packages/pip/_vendor/rich/scope.py +0 -86
  358. venv/Lib/site-packages/pip/_vendor/rich/screen.py +0 -54
  359. venv/Lib/site-packages/pip/_vendor/rich/segment.py +0 -752
  360. venv/Lib/site-packages/pip/_vendor/rich/spinner.py +0 -132
  361. venv/Lib/site-packages/pip/_vendor/rich/status.py +0 -131
  362. venv/Lib/site-packages/pip/_vendor/rich/style.py +0 -796
  363. venv/Lib/site-packages/pip/_vendor/rich/styled.py +0 -42
  364. venv/Lib/site-packages/pip/_vendor/rich/syntax.py +0 -985
  365. venv/Lib/site-packages/pip/_vendor/rich/table.py +0 -1006
  366. venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py +0 -153
  367. venv/Lib/site-packages/pip/_vendor/rich/text.py +0 -1361
  368. venv/Lib/site-packages/pip/_vendor/rich/theme.py +0 -115
  369. venv/Lib/site-packages/pip/_vendor/rich/themes.py +0 -5
  370. venv/Lib/site-packages/pip/_vendor/rich/traceback.py +0 -899
  371. venv/Lib/site-packages/pip/_vendor/rich/tree.py +0 -257
  372. venv/Lib/site-packages/pip/_vendor/tomli/__init__.py +0 -8
  373. venv/Lib/site-packages/pip/_vendor/tomli/_parser.py +0 -770
  374. venv/Lib/site-packages/pip/_vendor/tomli/_re.py +0 -112
  375. venv/Lib/site-packages/pip/_vendor/tomli/_types.py +0 -10
  376. venv/Lib/site-packages/pip/_vendor/tomli/py.typed +0 -1
  377. venv/Lib/site-packages/pip/_vendor/tomli_w/__init__.py +0 -4
  378. venv/Lib/site-packages/pip/_vendor/tomli_w/_writer.py +0 -229
  379. venv/Lib/site-packages/pip/_vendor/tomli_w/py.typed +0 -1
  380. venv/Lib/site-packages/pip/_vendor/truststore/__init__.py +0 -36
  381. venv/Lib/site-packages/pip/_vendor/truststore/_api.py +0 -333
  382. venv/Lib/site-packages/pip/_vendor/truststore/_macos.py +0 -571
  383. venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py +0 -66
  384. venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py +0 -31
  385. venv/Lib/site-packages/pip/_vendor/truststore/_windows.py +0 -567
  386. venv/Lib/site-packages/pip/_vendor/truststore/py.typed +0 -0
  387. venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py +0 -102
  388. venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py +0 -355
  389. venv/Lib/site-packages/pip/_vendor/urllib3/_version.py +0 -2
  390. venv/Lib/site-packages/pip/_vendor/urllib3/connection.py +0 -572
  391. venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py +0 -1140
  392. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py +0 -0
  393. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py +0 -36
  394. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py +0 -0
  395. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +0 -519
  396. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +0 -397
  397. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py +0 -314
  398. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py +0 -130
  399. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +0 -518
  400. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py +0 -920
  401. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py +0 -216
  402. venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py +0 -323
  403. venv/Lib/site-packages/pip/_vendor/urllib3/fields.py +0 -274
  404. venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py +0 -98
  405. venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py +0 -0
  406. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py +0 -0
  407. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +0 -51
  408. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py +0 -155
  409. venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py +0 -1076
  410. venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py +0 -540
  411. venv/Lib/site-packages/pip/_vendor/urllib3/request.py +0 -191
  412. venv/Lib/site-packages/pip/_vendor/urllib3/response.py +0 -879
  413. venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py +0 -49
  414. venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py +0 -149
  415. venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py +0 -57
  416. venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py +0 -22
  417. venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py +0 -137
  418. venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py +0 -107
  419. venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py +0 -622
  420. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py +0 -504
  421. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +0 -159
  422. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py +0 -221
  423. venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py +0 -271
  424. venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py +0 -435
  425. venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py +0 -152
  426. venv/Lib/site-packages/pip/py.typed +0 -4
  427. {cli_ih-0.6.3.1.dist-info → cli_ih-0.7.1.dist-info}/WHEEL +0 -0
@@ -1,1361 +0,0 @@
1
- import re
2
- from functools import partial, reduce
3
- from math import gcd
4
- from operator import itemgetter
5
- from typing import (
6
- TYPE_CHECKING,
7
- Any,
8
- Callable,
9
- Dict,
10
- Iterable,
11
- List,
12
- NamedTuple,
13
- Optional,
14
- Pattern,
15
- Tuple,
16
- Union,
17
- )
18
-
19
- from ._loop import loop_last
20
- from ._pick import pick_bool
21
- from ._wrap import divide_line
22
- from .align import AlignMethod
23
- from .cells import cell_len, set_cell_size
24
- from .containers import Lines
25
- from .control import strip_control_codes
26
- from .emoji import EmojiVariant
27
- from .jupyter import JupyterMixin
28
- from .measure import Measurement
29
- from .segment import Segment
30
- from .style import Style, StyleType
31
-
32
- if TYPE_CHECKING: # pragma: no cover
33
- from .console import Console, ConsoleOptions, JustifyMethod, OverflowMethod
34
-
35
- DEFAULT_JUSTIFY: "JustifyMethod" = "default"
36
- DEFAULT_OVERFLOW: "OverflowMethod" = "fold"
37
-
38
-
39
- _re_whitespace = re.compile(r"\s+$")
40
-
41
- TextType = Union[str, "Text"]
42
- """A plain string or a :class:`Text` instance."""
43
-
44
- GetStyleCallable = Callable[[str], Optional[StyleType]]
45
-
46
-
47
- class Span(NamedTuple):
48
- """A marked up region in some text."""
49
-
50
- start: int
51
- """Span start index."""
52
- end: int
53
- """Span end index."""
54
- style: Union[str, Style]
55
- """Style associated with the span."""
56
-
57
- def __repr__(self) -> str:
58
- return f"Span({self.start}, {self.end}, {self.style!r})"
59
-
60
- def __bool__(self) -> bool:
61
- return self.end > self.start
62
-
63
- def split(self, offset: int) -> Tuple["Span", Optional["Span"]]:
64
- """Split a span in to 2 from a given offset."""
65
-
66
- if offset < self.start:
67
- return self, None
68
- if offset >= self.end:
69
- return self, None
70
-
71
- start, end, style = self
72
- span1 = Span(start, min(end, offset), style)
73
- span2 = Span(span1.end, end, style)
74
- return span1, span2
75
-
76
- def move(self, offset: int) -> "Span":
77
- """Move start and end by a given offset.
78
-
79
- Args:
80
- offset (int): Number of characters to add to start and end.
81
-
82
- Returns:
83
- TextSpan: A new TextSpan with adjusted position.
84
- """
85
- start, end, style = self
86
- return Span(start + offset, end + offset, style)
87
-
88
- def right_crop(self, offset: int) -> "Span":
89
- """Crop the span at the given offset.
90
-
91
- Args:
92
- offset (int): A value between start and end.
93
-
94
- Returns:
95
- Span: A new (possibly smaller) span.
96
- """
97
- start, end, style = self
98
- if offset >= end:
99
- return self
100
- return Span(start, min(offset, end), style)
101
-
102
- def extend(self, cells: int) -> "Span":
103
- """Extend the span by the given number of cells.
104
-
105
- Args:
106
- cells (int): Additional space to add to end of span.
107
-
108
- Returns:
109
- Span: A span.
110
- """
111
- if cells:
112
- start, end, style = self
113
- return Span(start, end + cells, style)
114
- else:
115
- return self
116
-
117
-
118
- class Text(JupyterMixin):
119
- """Text with color / style.
120
-
121
- Args:
122
- text (str, optional): Default unstyled text. Defaults to "".
123
- style (Union[str, Style], optional): Base style for text. Defaults to "".
124
- justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
125
- overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
126
- no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
127
- end (str, optional): Character to end text with. Defaults to "\\\\n".
128
- tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
129
- spans (List[Span], optional). A list of predefined style spans. Defaults to None.
130
- """
131
-
132
- __slots__ = [
133
- "_text",
134
- "style",
135
- "justify",
136
- "overflow",
137
- "no_wrap",
138
- "end",
139
- "tab_size",
140
- "_spans",
141
- "_length",
142
- ]
143
-
144
- def __init__(
145
- self,
146
- text: str = "",
147
- style: Union[str, Style] = "",
148
- *,
149
- justify: Optional["JustifyMethod"] = None,
150
- overflow: Optional["OverflowMethod"] = None,
151
- no_wrap: Optional[bool] = None,
152
- end: str = "\n",
153
- tab_size: Optional[int] = None,
154
- spans: Optional[List[Span]] = None,
155
- ) -> None:
156
- sanitized_text = strip_control_codes(text)
157
- self._text = [sanitized_text]
158
- self.style = style
159
- self.justify: Optional["JustifyMethod"] = justify
160
- self.overflow: Optional["OverflowMethod"] = overflow
161
- self.no_wrap = no_wrap
162
- self.end = end
163
- self.tab_size = tab_size
164
- self._spans: List[Span] = spans or []
165
- self._length: int = len(sanitized_text)
166
-
167
- def __len__(self) -> int:
168
- return self._length
169
-
170
- def __bool__(self) -> bool:
171
- return bool(self._length)
172
-
173
- def __str__(self) -> str:
174
- return self.plain
175
-
176
- def __repr__(self) -> str:
177
- return f"<text {self.plain!r} {self._spans!r} {self.style!r}>"
178
-
179
- def __add__(self, other: Any) -> "Text":
180
- if isinstance(other, (str, Text)):
181
- result = self.copy()
182
- result.append(other)
183
- return result
184
- return NotImplemented
185
-
186
- def __eq__(self, other: object) -> bool:
187
- if not isinstance(other, Text):
188
- return NotImplemented
189
- return self.plain == other.plain and self._spans == other._spans
190
-
191
- def __contains__(self, other: object) -> bool:
192
- if isinstance(other, str):
193
- return other in self.plain
194
- elif isinstance(other, Text):
195
- return other.plain in self.plain
196
- return False
197
-
198
- def __getitem__(self, slice: Union[int, slice]) -> "Text":
199
- def get_text_at(offset: int) -> "Text":
200
- _Span = Span
201
- text = Text(
202
- self.plain[offset],
203
- spans=[
204
- _Span(0, 1, style)
205
- for start, end, style in self._spans
206
- if end > offset >= start
207
- ],
208
- end="",
209
- )
210
- return text
211
-
212
- if isinstance(slice, int):
213
- return get_text_at(slice)
214
- else:
215
- start, stop, step = slice.indices(len(self.plain))
216
- if step == 1:
217
- lines = self.divide([start, stop])
218
- return lines[1]
219
- else:
220
- # This would be a bit of work to implement efficiently
221
- # For now, its not required
222
- raise TypeError("slices with step!=1 are not supported")
223
-
224
- @property
225
- def cell_len(self) -> int:
226
- """Get the number of cells required to render this text."""
227
- return cell_len(self.plain)
228
-
229
- @property
230
- def markup(self) -> str:
231
- """Get console markup to render this Text.
232
-
233
- Returns:
234
- str: A string potentially creating markup tags.
235
- """
236
- from .markup import escape
237
-
238
- output: List[str] = []
239
-
240
- plain = self.plain
241
- markup_spans = [
242
- (0, False, self.style),
243
- *((span.start, False, span.style) for span in self._spans),
244
- *((span.end, True, span.style) for span in self._spans),
245
- (len(plain), True, self.style),
246
- ]
247
- markup_spans.sort(key=itemgetter(0, 1))
248
- position = 0
249
- append = output.append
250
- for offset, closing, style in markup_spans:
251
- if offset > position:
252
- append(escape(plain[position:offset]))
253
- position = offset
254
- if style:
255
- append(f"[/{style}]" if closing else f"[{style}]")
256
- markup = "".join(output)
257
- return markup
258
-
259
- @classmethod
260
- def from_markup(
261
- cls,
262
- text: str,
263
- *,
264
- style: Union[str, Style] = "",
265
- emoji: bool = True,
266
- emoji_variant: Optional[EmojiVariant] = None,
267
- justify: Optional["JustifyMethod"] = None,
268
- overflow: Optional["OverflowMethod"] = None,
269
- end: str = "\n",
270
- ) -> "Text":
271
- """Create Text instance from markup.
272
-
273
- Args:
274
- text (str): A string containing console markup.
275
- style (Union[str, Style], optional): Base style for text. Defaults to "".
276
- emoji (bool, optional): Also render emoji code. Defaults to True.
277
- emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None.
278
- justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
279
- overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
280
- end (str, optional): Character to end text with. Defaults to "\\\\n".
281
-
282
- Returns:
283
- Text: A Text instance with markup rendered.
284
- """
285
- from .markup import render
286
-
287
- rendered_text = render(text, style, emoji=emoji, emoji_variant=emoji_variant)
288
- rendered_text.justify = justify
289
- rendered_text.overflow = overflow
290
- rendered_text.end = end
291
- return rendered_text
292
-
293
- @classmethod
294
- def from_ansi(
295
- cls,
296
- text: str,
297
- *,
298
- style: Union[str, Style] = "",
299
- justify: Optional["JustifyMethod"] = None,
300
- overflow: Optional["OverflowMethod"] = None,
301
- no_wrap: Optional[bool] = None,
302
- end: str = "\n",
303
- tab_size: Optional[int] = 8,
304
- ) -> "Text":
305
- """Create a Text object from a string containing ANSI escape codes.
306
-
307
- Args:
308
- text (str): A string containing escape codes.
309
- style (Union[str, Style], optional): Base style for text. Defaults to "".
310
- justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
311
- overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
312
- no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
313
- end (str, optional): Character to end text with. Defaults to "\\\\n".
314
- tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
315
- """
316
- from .ansi import AnsiDecoder
317
-
318
- joiner = Text(
319
- "\n",
320
- justify=justify,
321
- overflow=overflow,
322
- no_wrap=no_wrap,
323
- end=end,
324
- tab_size=tab_size,
325
- style=style,
326
- )
327
- decoder = AnsiDecoder()
328
- result = joiner.join(line for line in decoder.decode(text))
329
- return result
330
-
331
- @classmethod
332
- def styled(
333
- cls,
334
- text: str,
335
- style: StyleType = "",
336
- *,
337
- justify: Optional["JustifyMethod"] = None,
338
- overflow: Optional["OverflowMethod"] = None,
339
- ) -> "Text":
340
- """Construct a Text instance with a pre-applied styled. A style applied in this way won't be used
341
- to pad the text when it is justified.
342
-
343
- Args:
344
- text (str): A string containing console markup.
345
- style (Union[str, Style]): Style to apply to the text. Defaults to "".
346
- justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
347
- overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
348
-
349
- Returns:
350
- Text: A text instance with a style applied to the entire string.
351
- """
352
- styled_text = cls(text, justify=justify, overflow=overflow)
353
- styled_text.stylize(style)
354
- return styled_text
355
-
356
- @classmethod
357
- def assemble(
358
- cls,
359
- *parts: Union[str, "Text", Tuple[str, StyleType]],
360
- style: Union[str, Style] = "",
361
- justify: Optional["JustifyMethod"] = None,
362
- overflow: Optional["OverflowMethod"] = None,
363
- no_wrap: Optional[bool] = None,
364
- end: str = "\n",
365
- tab_size: int = 8,
366
- meta: Optional[Dict[str, Any]] = None,
367
- ) -> "Text":
368
- """Construct a text instance by combining a sequence of strings with optional styles.
369
- The positional arguments should be either strings, or a tuple of string + style.
370
-
371
- Args:
372
- style (Union[str, Style], optional): Base style for text. Defaults to "".
373
- justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
374
- overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
375
- no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
376
- end (str, optional): Character to end text with. Defaults to "\\\\n".
377
- tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
378
- meta (Dict[str, Any], optional). Meta data to apply to text, or None for no meta data. Default to None
379
-
380
- Returns:
381
- Text: A new text instance.
382
- """
383
- text = cls(
384
- style=style,
385
- justify=justify,
386
- overflow=overflow,
387
- no_wrap=no_wrap,
388
- end=end,
389
- tab_size=tab_size,
390
- )
391
- append = text.append
392
- _Text = Text
393
- for part in parts:
394
- if isinstance(part, (_Text, str)):
395
- append(part)
396
- else:
397
- append(*part)
398
- if meta:
399
- text.apply_meta(meta)
400
- return text
401
-
402
- @property
403
- def plain(self) -> str:
404
- """Get the text as a single string."""
405
- if len(self._text) != 1:
406
- self._text[:] = ["".join(self._text)]
407
- return self._text[0]
408
-
409
- @plain.setter
410
- def plain(self, new_text: str) -> None:
411
- """Set the text to a new value."""
412
- if new_text != self.plain:
413
- sanitized_text = strip_control_codes(new_text)
414
- self._text[:] = [sanitized_text]
415
- old_length = self._length
416
- self._length = len(sanitized_text)
417
- if old_length > self._length:
418
- self._trim_spans()
419
-
420
- @property
421
- def spans(self) -> List[Span]:
422
- """Get a reference to the internal list of spans."""
423
- return self._spans
424
-
425
- @spans.setter
426
- def spans(self, spans: List[Span]) -> None:
427
- """Set spans."""
428
- self._spans = spans[:]
429
-
430
- def blank_copy(self, plain: str = "") -> "Text":
431
- """Return a new Text instance with copied metadata (but not the string or spans)."""
432
- copy_self = Text(
433
- plain,
434
- style=self.style,
435
- justify=self.justify,
436
- overflow=self.overflow,
437
- no_wrap=self.no_wrap,
438
- end=self.end,
439
- tab_size=self.tab_size,
440
- )
441
- return copy_self
442
-
443
- def copy(self) -> "Text":
444
- """Return a copy of this instance."""
445
- copy_self = Text(
446
- self.plain,
447
- style=self.style,
448
- justify=self.justify,
449
- overflow=self.overflow,
450
- no_wrap=self.no_wrap,
451
- end=self.end,
452
- tab_size=self.tab_size,
453
- )
454
- copy_self._spans[:] = self._spans
455
- return copy_self
456
-
457
- def stylize(
458
- self,
459
- style: Union[str, Style],
460
- start: int = 0,
461
- end: Optional[int] = None,
462
- ) -> None:
463
- """Apply a style to the text, or a portion of the text.
464
-
465
- Args:
466
- style (Union[str, Style]): Style instance or style definition to apply.
467
- start (int): Start offset (negative indexing is supported). Defaults to 0.
468
- end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
469
- """
470
- if style:
471
- length = len(self)
472
- if start < 0:
473
- start = length + start
474
- if end is None:
475
- end = length
476
- if end < 0:
477
- end = length + end
478
- if start >= length or end <= start:
479
- # Span not in text or not valid
480
- return
481
- self._spans.append(Span(start, min(length, end), style))
482
-
483
- def stylize_before(
484
- self,
485
- style: Union[str, Style],
486
- start: int = 0,
487
- end: Optional[int] = None,
488
- ) -> None:
489
- """Apply a style to the text, or a portion of the text. Styles will be applied before other styles already present.
490
-
491
- Args:
492
- style (Union[str, Style]): Style instance or style definition to apply.
493
- start (int): Start offset (negative indexing is supported). Defaults to 0.
494
- end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
495
- """
496
- if style:
497
- length = len(self)
498
- if start < 0:
499
- start = length + start
500
- if end is None:
501
- end = length
502
- if end < 0:
503
- end = length + end
504
- if start >= length or end <= start:
505
- # Span not in text or not valid
506
- return
507
- self._spans.insert(0, Span(start, min(length, end), style))
508
-
509
- def apply_meta(
510
- self, meta: Dict[str, Any], start: int = 0, end: Optional[int] = None
511
- ) -> None:
512
- """Apply metadata to the text, or a portion of the text.
513
-
514
- Args:
515
- meta (Dict[str, Any]): A dict of meta information.
516
- start (int): Start offset (negative indexing is supported). Defaults to 0.
517
- end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
518
-
519
- """
520
- style = Style.from_meta(meta)
521
- self.stylize(style, start=start, end=end)
522
-
523
- def on(self, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Text":
524
- """Apply event handlers (used by Textual project).
525
-
526
- Example:
527
- >>> from rich.text import Text
528
- >>> text = Text("hello world")
529
- >>> text.on(click="view.toggle('world')")
530
-
531
- Args:
532
- meta (Dict[str, Any]): Mapping of meta information.
533
- **handlers: Keyword args are prefixed with "@" to defined handlers.
534
-
535
- Returns:
536
- Text: Self is returned to method may be chained.
537
- """
538
- meta = {} if meta is None else meta
539
- meta.update({f"@{key}": value for key, value in handlers.items()})
540
- self.stylize(Style.from_meta(meta))
541
- return self
542
-
543
- def remove_suffix(self, suffix: str) -> None:
544
- """Remove a suffix if it exists.
545
-
546
- Args:
547
- suffix (str): Suffix to remove.
548
- """
549
- if self.plain.endswith(suffix):
550
- self.right_crop(len(suffix))
551
-
552
- def get_style_at_offset(self, console: "Console", offset: int) -> Style:
553
- """Get the style of a character at give offset.
554
-
555
- Args:
556
- console (~Console): Console where text will be rendered.
557
- offset (int): Offset in to text (negative indexing supported)
558
-
559
- Returns:
560
- Style: A Style instance.
561
- """
562
- # TODO: This is a little inefficient, it is only used by full justify
563
- if offset < 0:
564
- offset = len(self) + offset
565
- get_style = console.get_style
566
- style = get_style(self.style).copy()
567
- for start, end, span_style in self._spans:
568
- if end > offset >= start:
569
- style += get_style(span_style, default="")
570
- return style
571
-
572
- def extend_style(self, spaces: int) -> None:
573
- """Extend the Text given number of spaces where the spaces have the same style as the last character.
574
-
575
- Args:
576
- spaces (int): Number of spaces to add to the Text.
577
- """
578
- if spaces <= 0:
579
- return
580
- spans = self.spans
581
- new_spaces = " " * spaces
582
- if spans:
583
- end_offset = len(self)
584
- self._spans[:] = [
585
- span.extend(spaces) if span.end >= end_offset else span
586
- for span in spans
587
- ]
588
- self._text.append(new_spaces)
589
- self._length += spaces
590
- else:
591
- self.plain += new_spaces
592
-
593
- def highlight_regex(
594
- self,
595
- re_highlight: Union[Pattern[str], str],
596
- style: Optional[Union[GetStyleCallable, StyleType]] = None,
597
- *,
598
- style_prefix: str = "",
599
- ) -> int:
600
- """Highlight text with a regular expression, where group names are
601
- translated to styles.
602
-
603
- Args:
604
- re_highlight (Union[re.Pattern, str]): A regular expression object or string.
605
- style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable
606
- which accepts the matched text and returns a style. Defaults to None.
607
- style_prefix (str, optional): Optional prefix to add to style group names.
608
-
609
- Returns:
610
- int: Number of regex matches
611
- """
612
- count = 0
613
- append_span = self._spans.append
614
- _Span = Span
615
- plain = self.plain
616
- if isinstance(re_highlight, str):
617
- re_highlight = re.compile(re_highlight)
618
- for match in re_highlight.finditer(plain):
619
- get_span = match.span
620
- if style:
621
- start, end = get_span()
622
- match_style = style(plain[start:end]) if callable(style) else style
623
- if match_style is not None and end > start:
624
- append_span(_Span(start, end, match_style))
625
-
626
- count += 1
627
- for name in match.groupdict().keys():
628
- start, end = get_span(name)
629
- if start != -1 and end > start:
630
- append_span(_Span(start, end, f"{style_prefix}{name}"))
631
- return count
632
-
633
- def highlight_words(
634
- self,
635
- words: Iterable[str],
636
- style: Union[str, Style],
637
- *,
638
- case_sensitive: bool = True,
639
- ) -> int:
640
- """Highlight words with a style.
641
-
642
- Args:
643
- words (Iterable[str]): Words to highlight.
644
- style (Union[str, Style]): Style to apply.
645
- case_sensitive (bool, optional): Enable case sensitive matching. Defaults to True.
646
-
647
- Returns:
648
- int: Number of words highlighted.
649
- """
650
- re_words = "|".join(re.escape(word) for word in words)
651
- add_span = self._spans.append
652
- count = 0
653
- _Span = Span
654
- for match in re.finditer(
655
- re_words, self.plain, flags=0 if case_sensitive else re.IGNORECASE
656
- ):
657
- start, end = match.span(0)
658
- add_span(_Span(start, end, style))
659
- count += 1
660
- return count
661
-
662
- def rstrip(self) -> None:
663
- """Strip whitespace from end of text."""
664
- self.plain = self.plain.rstrip()
665
-
666
- def rstrip_end(self, size: int) -> None:
667
- """Remove whitespace beyond a certain width at the end of the text.
668
-
669
- Args:
670
- size (int): The desired size of the text.
671
- """
672
- text_length = len(self)
673
- if text_length > size:
674
- excess = text_length - size
675
- whitespace_match = _re_whitespace.search(self.plain)
676
- if whitespace_match is not None:
677
- whitespace_count = len(whitespace_match.group(0))
678
- self.right_crop(min(whitespace_count, excess))
679
-
680
- def set_length(self, new_length: int) -> None:
681
- """Set new length of the text, clipping or padding is required."""
682
- length = len(self)
683
- if length != new_length:
684
- if length < new_length:
685
- self.pad_right(new_length - length)
686
- else:
687
- self.right_crop(length - new_length)
688
-
689
- def __rich_console__(
690
- self, console: "Console", options: "ConsoleOptions"
691
- ) -> Iterable[Segment]:
692
- tab_size: int = console.tab_size if self.tab_size is None else self.tab_size
693
- justify = self.justify or options.justify or DEFAULT_JUSTIFY
694
-
695
- overflow = self.overflow or options.overflow or DEFAULT_OVERFLOW
696
-
697
- lines = self.wrap(
698
- console,
699
- options.max_width,
700
- justify=justify,
701
- overflow=overflow,
702
- tab_size=tab_size or 8,
703
- no_wrap=pick_bool(self.no_wrap, options.no_wrap, False),
704
- )
705
- all_lines = Text("\n").join(lines)
706
- yield from all_lines.render(console, end=self.end)
707
-
708
- def __rich_measure__(
709
- self, console: "Console", options: "ConsoleOptions"
710
- ) -> Measurement:
711
- text = self.plain
712
- lines = text.splitlines()
713
- max_text_width = max(cell_len(line) for line in lines) if lines else 0
714
- words = text.split()
715
- min_text_width = (
716
- max(cell_len(word) for word in words) if words else max_text_width
717
- )
718
- return Measurement(min_text_width, max_text_width)
719
-
720
- def render(self, console: "Console", end: str = "") -> Iterable["Segment"]:
721
- """Render the text as Segments.
722
-
723
- Args:
724
- console (Console): Console instance.
725
- end (Optional[str], optional): Optional end character.
726
-
727
- Returns:
728
- Iterable[Segment]: Result of render that may be written to the console.
729
- """
730
- _Segment = Segment
731
- text = self.plain
732
- if not self._spans:
733
- yield Segment(text)
734
- if end:
735
- yield _Segment(end)
736
- return
737
- get_style = partial(console.get_style, default=Style.null())
738
-
739
- enumerated_spans = list(enumerate(self._spans, 1))
740
- style_map = {index: get_style(span.style) for index, span in enumerated_spans}
741
- style_map[0] = get_style(self.style)
742
-
743
- spans = [
744
- (0, False, 0),
745
- *((span.start, False, index) for index, span in enumerated_spans),
746
- *((span.end, True, index) for index, span in enumerated_spans),
747
- (len(text), True, 0),
748
- ]
749
- spans.sort(key=itemgetter(0, 1))
750
-
751
- stack: List[int] = []
752
- stack_append = stack.append
753
- stack_pop = stack.remove
754
-
755
- style_cache: Dict[Tuple[Style, ...], Style] = {}
756
- style_cache_get = style_cache.get
757
- combine = Style.combine
758
-
759
- def get_current_style() -> Style:
760
- """Construct current style from stack."""
761
- styles = tuple(style_map[_style_id] for _style_id in sorted(stack))
762
- cached_style = style_cache_get(styles)
763
- if cached_style is not None:
764
- return cached_style
765
- current_style = combine(styles)
766
- style_cache[styles] = current_style
767
- return current_style
768
-
769
- for (offset, leaving, style_id), (next_offset, _, _) in zip(spans, spans[1:]):
770
- if leaving:
771
- stack_pop(style_id)
772
- else:
773
- stack_append(style_id)
774
- if next_offset > offset:
775
- yield _Segment(text[offset:next_offset], get_current_style())
776
- if end:
777
- yield _Segment(end)
778
-
779
- def join(self, lines: Iterable["Text"]) -> "Text":
780
- """Join text together with this instance as the separator.
781
-
782
- Args:
783
- lines (Iterable[Text]): An iterable of Text instances to join.
784
-
785
- Returns:
786
- Text: A new text instance containing join text.
787
- """
788
-
789
- new_text = self.blank_copy()
790
-
791
- def iter_text() -> Iterable["Text"]:
792
- if self.plain:
793
- for last, line in loop_last(lines):
794
- yield line
795
- if not last:
796
- yield self
797
- else:
798
- yield from lines
799
-
800
- extend_text = new_text._text.extend
801
- append_span = new_text._spans.append
802
- extend_spans = new_text._spans.extend
803
- offset = 0
804
- _Span = Span
805
-
806
- for text in iter_text():
807
- extend_text(text._text)
808
- if text.style:
809
- append_span(_Span(offset, offset + len(text), text.style))
810
- extend_spans(
811
- _Span(offset + start, offset + end, style)
812
- for start, end, style in text._spans
813
- )
814
- offset += len(text)
815
- new_text._length = offset
816
- return new_text
817
-
818
- def expand_tabs(self, tab_size: Optional[int] = None) -> None:
819
- """Converts tabs to spaces.
820
-
821
- Args:
822
- tab_size (int, optional): Size of tabs. Defaults to 8.
823
-
824
- """
825
- if "\t" not in self.plain:
826
- return
827
- if tab_size is None:
828
- tab_size = self.tab_size
829
- if tab_size is None:
830
- tab_size = 8
831
-
832
- new_text: List[Text] = []
833
- append = new_text.append
834
-
835
- for line in self.split("\n", include_separator=True):
836
- if "\t" not in line.plain:
837
- append(line)
838
- else:
839
- cell_position = 0
840
- parts = line.split("\t", include_separator=True)
841
- for part in parts:
842
- if part.plain.endswith("\t"):
843
- part._text[-1] = part._text[-1][:-1] + " "
844
- cell_position += part.cell_len
845
- tab_remainder = cell_position % tab_size
846
- if tab_remainder:
847
- spaces = tab_size - tab_remainder
848
- part.extend_style(spaces)
849
- cell_position += spaces
850
- else:
851
- cell_position += part.cell_len
852
- append(part)
853
-
854
- result = Text("").join(new_text)
855
-
856
- self._text = [result.plain]
857
- self._length = len(self.plain)
858
- self._spans[:] = result._spans
859
-
860
- def truncate(
861
- self,
862
- max_width: int,
863
- *,
864
- overflow: Optional["OverflowMethod"] = None,
865
- pad: bool = False,
866
- ) -> None:
867
- """Truncate text if it is longer that a given width.
868
-
869
- Args:
870
- max_width (int): Maximum number of characters in text.
871
- overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None, to use self.overflow.
872
- pad (bool, optional): Pad with spaces if the length is less than max_width. Defaults to False.
873
- """
874
- _overflow = overflow or self.overflow or DEFAULT_OVERFLOW
875
- if _overflow != "ignore":
876
- length = cell_len(self.plain)
877
- if length > max_width:
878
- if _overflow == "ellipsis":
879
- self.plain = set_cell_size(self.plain, max_width - 1) + "…"
880
- else:
881
- self.plain = set_cell_size(self.plain, max_width)
882
- if pad and length < max_width:
883
- spaces = max_width - length
884
- self._text = [f"{self.plain}{' ' * spaces}"]
885
- self._length = len(self.plain)
886
-
887
- def _trim_spans(self) -> None:
888
- """Remove or modify any spans that are over the end of the text."""
889
- max_offset = len(self.plain)
890
- _Span = Span
891
- self._spans[:] = [
892
- (
893
- span
894
- if span.end < max_offset
895
- else _Span(span.start, min(max_offset, span.end), span.style)
896
- )
897
- for span in self._spans
898
- if span.start < max_offset
899
- ]
900
-
901
- def pad(self, count: int, character: str = " ") -> None:
902
- """Pad left and right with a given number of characters.
903
-
904
- Args:
905
- count (int): Width of padding.
906
- character (str): The character to pad with. Must be a string of length 1.
907
- """
908
- assert len(character) == 1, "Character must be a string of length 1"
909
- if count:
910
- pad_characters = character * count
911
- self.plain = f"{pad_characters}{self.plain}{pad_characters}"
912
- _Span = Span
913
- self._spans[:] = [
914
- _Span(start + count, end + count, style)
915
- for start, end, style in self._spans
916
- ]
917
-
918
- def pad_left(self, count: int, character: str = " ") -> None:
919
- """Pad the left with a given character.
920
-
921
- Args:
922
- count (int): Number of characters to pad.
923
- character (str, optional): Character to pad with. Defaults to " ".
924
- """
925
- assert len(character) == 1, "Character must be a string of length 1"
926
- if count:
927
- self.plain = f"{character * count}{self.plain}"
928
- _Span = Span
929
- self._spans[:] = [
930
- _Span(start + count, end + count, style)
931
- for start, end, style in self._spans
932
- ]
933
-
934
- def pad_right(self, count: int, character: str = " ") -> None:
935
- """Pad the right with a given character.
936
-
937
- Args:
938
- count (int): Number of characters to pad.
939
- character (str, optional): Character to pad with. Defaults to " ".
940
- """
941
- assert len(character) == 1, "Character must be a string of length 1"
942
- if count:
943
- self.plain = f"{self.plain}{character * count}"
944
-
945
- def align(self, align: AlignMethod, width: int, character: str = " ") -> None:
946
- """Align text to a given width.
947
-
948
- Args:
949
- align (AlignMethod): One of "left", "center", or "right".
950
- width (int): Desired width.
951
- character (str, optional): Character to pad with. Defaults to " ".
952
- """
953
- self.truncate(width)
954
- excess_space = width - cell_len(self.plain)
955
- if excess_space:
956
- if align == "left":
957
- self.pad_right(excess_space, character)
958
- elif align == "center":
959
- left = excess_space // 2
960
- self.pad_left(left, character)
961
- self.pad_right(excess_space - left, character)
962
- else:
963
- self.pad_left(excess_space, character)
964
-
965
- def append(
966
- self, text: Union["Text", str], style: Optional[Union[str, "Style"]] = None
967
- ) -> "Text":
968
- """Add text with an optional style.
969
-
970
- Args:
971
- text (Union[Text, str]): A str or Text to append.
972
- style (str, optional): A style name. Defaults to None.
973
-
974
- Returns:
975
- Text: Returns self for chaining.
976
- """
977
-
978
- if not isinstance(text, (str, Text)):
979
- raise TypeError("Only str or Text can be appended to Text")
980
-
981
- if len(text):
982
- if isinstance(text, str):
983
- sanitized_text = strip_control_codes(text)
984
- self._text.append(sanitized_text)
985
- offset = len(self)
986
- text_length = len(sanitized_text)
987
- if style:
988
- self._spans.append(Span(offset, offset + text_length, style))
989
- self._length += text_length
990
- elif isinstance(text, Text):
991
- _Span = Span
992
- if style is not None:
993
- raise ValueError(
994
- "style must not be set when appending Text instance"
995
- )
996
- text_length = self._length
997
- if text.style:
998
- self._spans.append(
999
- _Span(text_length, text_length + len(text), text.style)
1000
- )
1001
- self._text.append(text.plain)
1002
- self._spans.extend(
1003
- _Span(start + text_length, end + text_length, style)
1004
- for start, end, style in text._spans.copy()
1005
- )
1006
- self._length += len(text)
1007
- return self
1008
-
1009
- def append_text(self, text: "Text") -> "Text":
1010
- """Append another Text instance. This method is more performant that Text.append, but
1011
- only works for Text.
1012
-
1013
- Args:
1014
- text (Text): The Text instance to append to this instance.
1015
-
1016
- Returns:
1017
- Text: Returns self for chaining.
1018
- """
1019
- _Span = Span
1020
- text_length = self._length
1021
- if text.style:
1022
- self._spans.append(_Span(text_length, text_length + len(text), text.style))
1023
- self._text.append(text.plain)
1024
- self._spans.extend(
1025
- _Span(start + text_length, end + text_length, style)
1026
- for start, end, style in text._spans.copy()
1027
- )
1028
- self._length += len(text)
1029
- return self
1030
-
1031
- def append_tokens(
1032
- self, tokens: Iterable[Tuple[str, Optional[StyleType]]]
1033
- ) -> "Text":
1034
- """Append iterable of str and style. Style may be a Style instance or a str style definition.
1035
-
1036
- Args:
1037
- tokens (Iterable[Tuple[str, Optional[StyleType]]]): An iterable of tuples containing str content and style.
1038
-
1039
- Returns:
1040
- Text: Returns self for chaining.
1041
- """
1042
- append_text = self._text.append
1043
- append_span = self._spans.append
1044
- _Span = Span
1045
- offset = len(self)
1046
- for content, style in tokens:
1047
- content = strip_control_codes(content)
1048
- append_text(content)
1049
- if style:
1050
- append_span(_Span(offset, offset + len(content), style))
1051
- offset += len(content)
1052
- self._length = offset
1053
- return self
1054
-
1055
- def copy_styles(self, text: "Text") -> None:
1056
- """Copy styles from another Text instance.
1057
-
1058
- Args:
1059
- text (Text): A Text instance to copy styles from, must be the same length.
1060
- """
1061
- self._spans.extend(text._spans)
1062
-
1063
- def split(
1064
- self,
1065
- separator: str = "\n",
1066
- *,
1067
- include_separator: bool = False,
1068
- allow_blank: bool = False,
1069
- ) -> Lines:
1070
- """Split rich text in to lines, preserving styles.
1071
-
1072
- Args:
1073
- separator (str, optional): String to split on. Defaults to "\\\\n".
1074
- include_separator (bool, optional): Include the separator in the lines. Defaults to False.
1075
- allow_blank (bool, optional): Return a blank line if the text ends with a separator. Defaults to False.
1076
-
1077
- Returns:
1078
- List[RichText]: A list of rich text, one per line of the original.
1079
- """
1080
- assert separator, "separator must not be empty"
1081
-
1082
- text = self.plain
1083
- if separator not in text:
1084
- return Lines([self.copy()])
1085
-
1086
- if include_separator:
1087
- lines = self.divide(
1088
- match.end() for match in re.finditer(re.escape(separator), text)
1089
- )
1090
- else:
1091
-
1092
- def flatten_spans() -> Iterable[int]:
1093
- for match in re.finditer(re.escape(separator), text):
1094
- start, end = match.span()
1095
- yield start
1096
- yield end
1097
-
1098
- lines = Lines(
1099
- line for line in self.divide(flatten_spans()) if line.plain != separator
1100
- )
1101
-
1102
- if not allow_blank and text.endswith(separator):
1103
- lines.pop()
1104
-
1105
- return lines
1106
-
1107
- def divide(self, offsets: Iterable[int]) -> Lines:
1108
- """Divide text in to a number of lines at given offsets.
1109
-
1110
- Args:
1111
- offsets (Iterable[int]): Offsets used to divide text.
1112
-
1113
- Returns:
1114
- Lines: New RichText instances between offsets.
1115
- """
1116
- _offsets = list(offsets)
1117
-
1118
- if not _offsets:
1119
- return Lines([self.copy()])
1120
-
1121
- text = self.plain
1122
- text_length = len(text)
1123
- divide_offsets = [0, *_offsets, text_length]
1124
- line_ranges = list(zip(divide_offsets, divide_offsets[1:]))
1125
-
1126
- style = self.style
1127
- justify = self.justify
1128
- overflow = self.overflow
1129
- _Text = Text
1130
- new_lines = Lines(
1131
- _Text(
1132
- text[start:end],
1133
- style=style,
1134
- justify=justify,
1135
- overflow=overflow,
1136
- )
1137
- for start, end in line_ranges
1138
- )
1139
- if not self._spans:
1140
- return new_lines
1141
-
1142
- _line_appends = [line._spans.append for line in new_lines._lines]
1143
- line_count = len(line_ranges)
1144
- _Span = Span
1145
-
1146
- for span_start, span_end, style in self._spans:
1147
- lower_bound = 0
1148
- upper_bound = line_count
1149
- start_line_no = (lower_bound + upper_bound) // 2
1150
-
1151
- while True:
1152
- line_start, line_end = line_ranges[start_line_no]
1153
- if span_start < line_start:
1154
- upper_bound = start_line_no - 1
1155
- elif span_start > line_end:
1156
- lower_bound = start_line_no + 1
1157
- else:
1158
- break
1159
- start_line_no = (lower_bound + upper_bound) // 2
1160
-
1161
- if span_end < line_end:
1162
- end_line_no = start_line_no
1163
- else:
1164
- end_line_no = lower_bound = start_line_no
1165
- upper_bound = line_count
1166
-
1167
- while True:
1168
- line_start, line_end = line_ranges[end_line_no]
1169
- if span_end < line_start:
1170
- upper_bound = end_line_no - 1
1171
- elif span_end > line_end:
1172
- lower_bound = end_line_no + 1
1173
- else:
1174
- break
1175
- end_line_no = (lower_bound + upper_bound) // 2
1176
-
1177
- for line_no in range(start_line_no, end_line_no + 1):
1178
- line_start, line_end = line_ranges[line_no]
1179
- new_start = max(0, span_start - line_start)
1180
- new_end = min(span_end - line_start, line_end - line_start)
1181
- if new_end > new_start:
1182
- _line_appends[line_no](_Span(new_start, new_end, style))
1183
-
1184
- return new_lines
1185
-
1186
- def right_crop(self, amount: int = 1) -> None:
1187
- """Remove a number of characters from the end of the text."""
1188
- max_offset = len(self.plain) - amount
1189
- _Span = Span
1190
- self._spans[:] = [
1191
- (
1192
- span
1193
- if span.end < max_offset
1194
- else _Span(span.start, min(max_offset, span.end), span.style)
1195
- )
1196
- for span in self._spans
1197
- if span.start < max_offset
1198
- ]
1199
- self._text = [self.plain[:-amount]]
1200
- self._length -= amount
1201
-
1202
- def wrap(
1203
- self,
1204
- console: "Console",
1205
- width: int,
1206
- *,
1207
- justify: Optional["JustifyMethod"] = None,
1208
- overflow: Optional["OverflowMethod"] = None,
1209
- tab_size: int = 8,
1210
- no_wrap: Optional[bool] = None,
1211
- ) -> Lines:
1212
- """Word wrap the text.
1213
-
1214
- Args:
1215
- console (Console): Console instance.
1216
- width (int): Number of cells available per line.
1217
- justify (str, optional): Justify method: "default", "left", "center", "full", "right". Defaults to "default".
1218
- overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None.
1219
- tab_size (int, optional): Default tab size. Defaults to 8.
1220
- no_wrap (bool, optional): Disable wrapping, Defaults to False.
1221
-
1222
- Returns:
1223
- Lines: Number of lines.
1224
- """
1225
- wrap_justify = justify or self.justify or DEFAULT_JUSTIFY
1226
- wrap_overflow = overflow or self.overflow or DEFAULT_OVERFLOW
1227
-
1228
- no_wrap = pick_bool(no_wrap, self.no_wrap, False) or overflow == "ignore"
1229
-
1230
- lines = Lines()
1231
- for line in self.split(allow_blank=True):
1232
- if "\t" in line:
1233
- line.expand_tabs(tab_size)
1234
- if no_wrap:
1235
- new_lines = Lines([line])
1236
- else:
1237
- offsets = divide_line(str(line), width, fold=wrap_overflow == "fold")
1238
- new_lines = line.divide(offsets)
1239
- for line in new_lines:
1240
- line.rstrip_end(width)
1241
- if wrap_justify:
1242
- new_lines.justify(
1243
- console, width, justify=wrap_justify, overflow=wrap_overflow
1244
- )
1245
- for line in new_lines:
1246
- line.truncate(width, overflow=wrap_overflow)
1247
- lines.extend(new_lines)
1248
- return lines
1249
-
1250
- def fit(self, width: int) -> Lines:
1251
- """Fit the text in to given width by chopping in to lines.
1252
-
1253
- Args:
1254
- width (int): Maximum characters in a line.
1255
-
1256
- Returns:
1257
- Lines: Lines container.
1258
- """
1259
- lines: Lines = Lines()
1260
- append = lines.append
1261
- for line in self.split():
1262
- line.set_length(width)
1263
- append(line)
1264
- return lines
1265
-
1266
- def detect_indentation(self) -> int:
1267
- """Auto-detect indentation of code.
1268
-
1269
- Returns:
1270
- int: Number of spaces used to indent code.
1271
- """
1272
-
1273
- _indentations = {
1274
- len(match.group(1))
1275
- for match in re.finditer(r"^( *)(.*)$", self.plain, flags=re.MULTILINE)
1276
- }
1277
-
1278
- try:
1279
- indentation = (
1280
- reduce(gcd, [indent for indent in _indentations if not indent % 2]) or 1
1281
- )
1282
- except TypeError:
1283
- indentation = 1
1284
-
1285
- return indentation
1286
-
1287
- def with_indent_guides(
1288
- self,
1289
- indent_size: Optional[int] = None,
1290
- *,
1291
- character: str = "│",
1292
- style: StyleType = "dim green",
1293
- ) -> "Text":
1294
- """Adds indent guide lines to text.
1295
-
1296
- Args:
1297
- indent_size (Optional[int]): Size of indentation, or None to auto detect. Defaults to None.
1298
- character (str, optional): Character to use for indentation. Defaults to "│".
1299
- style (Union[Style, str], optional): Style of indent guides.
1300
-
1301
- Returns:
1302
- Text: New text with indentation guides.
1303
- """
1304
-
1305
- _indent_size = self.detect_indentation() if indent_size is None else indent_size
1306
-
1307
- text = self.copy()
1308
- text.expand_tabs()
1309
- indent_line = f"{character}{' ' * (_indent_size - 1)}"
1310
-
1311
- re_indent = re.compile(r"^( *)(.*)$")
1312
- new_lines: List[Text] = []
1313
- add_line = new_lines.append
1314
- blank_lines = 0
1315
- for line in text.split(allow_blank=True):
1316
- match = re_indent.match(line.plain)
1317
- if not match or not match.group(2):
1318
- blank_lines += 1
1319
- continue
1320
- indent = match.group(1)
1321
- full_indents, remaining_space = divmod(len(indent), _indent_size)
1322
- new_indent = f"{indent_line * full_indents}{' ' * remaining_space}"
1323
- line.plain = new_indent + line.plain[len(new_indent) :]
1324
- line.stylize(style, 0, len(new_indent))
1325
- if blank_lines:
1326
- new_lines.extend([Text(new_indent, style=style)] * blank_lines)
1327
- blank_lines = 0
1328
- add_line(line)
1329
- if blank_lines:
1330
- new_lines.extend([Text("", style=style)] * blank_lines)
1331
-
1332
- new_text = text.blank_copy("\n").join(new_lines)
1333
- return new_text
1334
-
1335
-
1336
- if __name__ == "__main__": # pragma: no cover
1337
- from pip._vendor.rich.console import Console
1338
-
1339
- text = Text(
1340
- """\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"""
1341
- )
1342
- text.highlight_words(["Lorem"], "bold")
1343
- text.highlight_words(["ipsum"], "italic")
1344
-
1345
- console = Console()
1346
-
1347
- console.rule("justify='left'")
1348
- console.print(text, style="red")
1349
- console.print()
1350
-
1351
- console.rule("justify='center'")
1352
- console.print(text, style="green", justify="center")
1353
- console.print()
1354
-
1355
- console.rule("justify='right'")
1356
- console.print(text, style="blue", justify="right")
1357
- console.print()
1358
-
1359
- console.rule("justify='full'")
1360
- console.print(text, style="magenta", justify="full")
1361
- console.print()