webull-openapi-python-sdk 1.0.0__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 (295) hide show
  1. samples/__init__.py +1 -0
  2. samples/data/__init__.py +1 -0
  3. samples/data/data_client.py +57 -0
  4. samples/data/data_streaming_client.py +86 -0
  5. samples/data/data_streaming_client_async.py +101 -0
  6. samples/trade/__init__.py +0 -0
  7. samples/trade/trade_client.py +163 -0
  8. samples/trade/trade_client_v2.py +181 -0
  9. samples/trade/trade_event_client.py +47 -0
  10. webull/__init__.py +1 -0
  11. webull/core/__init__.py +12 -0
  12. webull/core/auth/__init__.py +0 -0
  13. webull/core/auth/algorithm/__init__.py +0 -0
  14. webull/core/auth/algorithm/sha_hmac1.py +65 -0
  15. webull/core/auth/algorithm/sha_hmac256.py +75 -0
  16. webull/core/auth/composer/__init__.py +0 -0
  17. webull/core/auth/composer/default_signature_composer.py +125 -0
  18. webull/core/auth/credentials.py +46 -0
  19. webull/core/auth/signers/__init__.py +0 -0
  20. webull/core/auth/signers/app_key_signer.py +72 -0
  21. webull/core/auth/signers/signer.py +48 -0
  22. webull/core/auth/signers/signer_factory.py +58 -0
  23. webull/core/cache/__init__.py +225 -0
  24. webull/core/client.py +410 -0
  25. webull/core/common/__init__.py +0 -0
  26. webull/core/common/api_type.py +19 -0
  27. webull/core/common/easy_enum.py +35 -0
  28. webull/core/common/region.py +7 -0
  29. webull/core/compat.py +85 -0
  30. webull/core/context/__init__.py +0 -0
  31. webull/core/context/request_context_holder.py +33 -0
  32. webull/core/data/endpoints.json +22 -0
  33. webull/core/data/retry_config.json +15 -0
  34. webull/core/endpoint/__init__.py +8 -0
  35. webull/core/endpoint/chained_endpoint_resolver.py +57 -0
  36. webull/core/endpoint/default_endpoint_resolver.py +60 -0
  37. webull/core/endpoint/local_config_regional_endpoint_resolver.py +77 -0
  38. webull/core/endpoint/resolver_endpoint_request.py +46 -0
  39. webull/core/endpoint/user_customized_endpoint_resolver.py +55 -0
  40. webull/core/exception/__init__.py +0 -0
  41. webull/core/exception/error_code.py +23 -0
  42. webull/core/exception/error_msg.py +21 -0
  43. webull/core/exception/exceptions.py +53 -0
  44. webull/core/headers.py +57 -0
  45. webull/core/http/__init__.py +0 -0
  46. webull/core/http/initializer/__init__.py +0 -0
  47. webull/core/http/initializer/client_initializer.py +79 -0
  48. webull/core/http/initializer/token/__init__.py +0 -0
  49. webull/core/http/initializer/token/bean/__init__.py +0 -0
  50. webull/core/http/initializer/token/bean/access_token.py +40 -0
  51. webull/core/http/initializer/token/bean/check_token_request.py +44 -0
  52. webull/core/http/initializer/token/bean/create_token_request.py +45 -0
  53. webull/core/http/initializer/token/bean/refresh_token_request.py +44 -0
  54. webull/core/http/initializer/token/token_manager.py +208 -0
  55. webull/core/http/initializer/token/token_operation.py +72 -0
  56. webull/core/http/method_type.py +43 -0
  57. webull/core/http/protocol_type.py +43 -0
  58. webull/core/http/request.py +121 -0
  59. webull/core/http/response.py +166 -0
  60. webull/core/request.py +278 -0
  61. webull/core/retry/__init__.py +0 -0
  62. webull/core/retry/backoff_strategy.py +102 -0
  63. webull/core/retry/retry_condition.py +214 -0
  64. webull/core/retry/retry_policy.py +63 -0
  65. webull/core/retry/retry_policy_context.py +51 -0
  66. webull/core/utils/__init__.py +0 -0
  67. webull/core/utils/common.py +62 -0
  68. webull/core/utils/data.py +25 -0
  69. webull/core/utils/desensitize.py +33 -0
  70. webull/core/utils/validation.py +49 -0
  71. webull/core/vendored/__init__.py +0 -0
  72. webull/core/vendored/requests/__init__.py +94 -0
  73. webull/core/vendored/requests/__version__.py +28 -0
  74. webull/core/vendored/requests/_internal_utils.py +56 -0
  75. webull/core/vendored/requests/adapters.py +539 -0
  76. webull/core/vendored/requests/api.py +166 -0
  77. webull/core/vendored/requests/auth.py +307 -0
  78. webull/core/vendored/requests/certs.py +34 -0
  79. webull/core/vendored/requests/compat.py +85 -0
  80. webull/core/vendored/requests/cookies.py +555 -0
  81. webull/core/vendored/requests/exceptions.py +136 -0
  82. webull/core/vendored/requests/help.py +134 -0
  83. webull/core/vendored/requests/hooks.py +48 -0
  84. webull/core/vendored/requests/models.py +960 -0
  85. webull/core/vendored/requests/packages/__init__.py +17 -0
  86. webull/core/vendored/requests/packages/certifi/__init__.py +17 -0
  87. webull/core/vendored/requests/packages/certifi/__main__.py +16 -0
  88. webull/core/vendored/requests/packages/certifi/cacert.pem +4433 -0
  89. webull/core/vendored/requests/packages/certifi/core.py +51 -0
  90. webull/core/vendored/requests/packages/chardet/__init__.py +53 -0
  91. webull/core/vendored/requests/packages/chardet/big5freq.py +400 -0
  92. webull/core/vendored/requests/packages/chardet/big5prober.py +61 -0
  93. webull/core/vendored/requests/packages/chardet/chardistribution.py +247 -0
  94. webull/core/vendored/requests/packages/chardet/charsetgroupprober.py +120 -0
  95. webull/core/vendored/requests/packages/chardet/charsetprober.py +159 -0
  96. webull/core/vendored/requests/packages/chardet/cli/__init__.py +1 -0
  97. webull/core/vendored/requests/packages/chardet/cli/chardetect.py +99 -0
  98. webull/core/vendored/requests/packages/chardet/codingstatemachine.py +102 -0
  99. webull/core/vendored/requests/packages/chardet/compat.py +48 -0
  100. webull/core/vendored/requests/packages/chardet/cp949prober.py +63 -0
  101. webull/core/vendored/requests/packages/chardet/enums.py +90 -0
  102. webull/core/vendored/requests/packages/chardet/escprober.py +115 -0
  103. webull/core/vendored/requests/packages/chardet/escsm.py +260 -0
  104. webull/core/vendored/requests/packages/chardet/eucjpprober.py +106 -0
  105. webull/core/vendored/requests/packages/chardet/euckrfreq.py +209 -0
  106. webull/core/vendored/requests/packages/chardet/euckrprober.py +61 -0
  107. webull/core/vendored/requests/packages/chardet/euctwfreq.py +401 -0
  108. webull/core/vendored/requests/packages/chardet/euctwprober.py +60 -0
  109. webull/core/vendored/requests/packages/chardet/gb2312freq.py +297 -0
  110. webull/core/vendored/requests/packages/chardet/gb2312prober.py +60 -0
  111. webull/core/vendored/requests/packages/chardet/hebrewprober.py +306 -0
  112. webull/core/vendored/requests/packages/chardet/jisfreq.py +339 -0
  113. webull/core/vendored/requests/packages/chardet/jpcntx.py +247 -0
  114. webull/core/vendored/requests/packages/chardet/langbulgarianmodel.py +242 -0
  115. webull/core/vendored/requests/packages/chardet/langcyrillicmodel.py +347 -0
  116. webull/core/vendored/requests/packages/chardet/langgreekmodel.py +239 -0
  117. webull/core/vendored/requests/packages/chardet/langhebrewmodel.py +214 -0
  118. webull/core/vendored/requests/packages/chardet/langhungarianmodel.py +239 -0
  119. webull/core/vendored/requests/packages/chardet/langthaimodel.py +213 -0
  120. webull/core/vendored/requests/packages/chardet/langturkishmodel.py +207 -0
  121. webull/core/vendored/requests/packages/chardet/latin1prober.py +159 -0
  122. webull/core/vendored/requests/packages/chardet/mbcharsetprober.py +105 -0
  123. webull/core/vendored/requests/packages/chardet/mbcsgroupprober.py +68 -0
  124. webull/core/vendored/requests/packages/chardet/mbcssm.py +586 -0
  125. webull/core/vendored/requests/packages/chardet/sbcharsetprober.py +146 -0
  126. webull/core/vendored/requests/packages/chardet/sbcsgroupprober.py +87 -0
  127. webull/core/vendored/requests/packages/chardet/sjisprober.py +106 -0
  128. webull/core/vendored/requests/packages/chardet/universaldetector.py +300 -0
  129. webull/core/vendored/requests/packages/chardet/utf8prober.py +96 -0
  130. webull/core/vendored/requests/packages/chardet/version.py +23 -0
  131. webull/core/vendored/requests/packages/urllib3/__init__.py +114 -0
  132. webull/core/vendored/requests/packages/urllib3/_collections.py +346 -0
  133. webull/core/vendored/requests/packages/urllib3/connection.py +405 -0
  134. webull/core/vendored/requests/packages/urllib3/connectionpool.py +910 -0
  135. webull/core/vendored/requests/packages/urllib3/contrib/__init__.py +0 -0
  136. webull/core/vendored/requests/packages/urllib3/contrib/_appengine_environ.py +44 -0
  137. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/__init__.py +0 -0
  138. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/bindings.py +607 -0
  139. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/low_level.py +360 -0
  140. webull/core/vendored/requests/packages/urllib3/contrib/appengine.py +303 -0
  141. webull/core/vendored/requests/packages/urllib3/contrib/ntlmpool.py +125 -0
  142. webull/core/vendored/requests/packages/urllib3/contrib/pyopenssl.py +484 -0
  143. webull/core/vendored/requests/packages/urllib3/contrib/securetransport.py +818 -0
  144. webull/core/vendored/requests/packages/urllib3/contrib/socks.py +206 -0
  145. webull/core/vendored/requests/packages/urllib3/exceptions.py +260 -0
  146. webull/core/vendored/requests/packages/urllib3/fields.py +192 -0
  147. webull/core/vendored/requests/packages/urllib3/filepost.py +112 -0
  148. webull/core/vendored/requests/packages/urllib3/packages/__init__.py +19 -0
  149. webull/core/vendored/requests/packages/urllib3/packages/backports/__init__.py +0 -0
  150. webull/core/vendored/requests/packages/urllib3/packages/backports/makefile.py +67 -0
  151. webull/core/vendored/requests/packages/urllib3/packages/ordered_dict.py +273 -0
  152. webull/core/vendored/requests/packages/urllib3/packages/six.py +882 -0
  153. webull/core/vendored/requests/packages/urllib3/packages/socks.py +887 -0
  154. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +19 -0
  155. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py +170 -0
  156. webull/core/vendored/requests/packages/urllib3/poolmanager.py +467 -0
  157. webull/core/vendored/requests/packages/urllib3/request.py +164 -0
  158. webull/core/vendored/requests/packages/urllib3/response.py +721 -0
  159. webull/core/vendored/requests/packages/urllib3/util/__init__.py +68 -0
  160. webull/core/vendored/requests/packages/urllib3/util/connection.py +148 -0
  161. webull/core/vendored/requests/packages/urllib3/util/queue.py +35 -0
  162. webull/core/vendored/requests/packages/urllib3/util/request.py +132 -0
  163. webull/core/vendored/requests/packages/urllib3/util/response.py +101 -0
  164. webull/core/vendored/requests/packages/urllib3/util/retry.py +426 -0
  165. webull/core/vendored/requests/packages/urllib3/util/selectors.py +601 -0
  166. webull/core/vendored/requests/packages/urllib3/util/ssl_.py +396 -0
  167. webull/core/vendored/requests/packages/urllib3/util/timeout.py +256 -0
  168. webull/core/vendored/requests/packages/urllib3/util/url.py +252 -0
  169. webull/core/vendored/requests/packages/urllib3/util/wait.py +164 -0
  170. webull/core/vendored/requests/packages.py +28 -0
  171. webull/core/vendored/requests/sessions.py +750 -0
  172. webull/core/vendored/requests/status_codes.py +105 -0
  173. webull/core/vendored/requests/structures.py +119 -0
  174. webull/core/vendored/requests/utils.py +916 -0
  175. webull/core/vendored/six.py +905 -0
  176. webull/data/__init__.py +3 -0
  177. webull/data/common/__init__.py +0 -0
  178. webull/data/common/category.py +26 -0
  179. webull/data/common/connect_ack.py +29 -0
  180. webull/data/common/direction.py +25 -0
  181. webull/data/common/exchange_code.py +33 -0
  182. webull/data/common/exercise_style.py +22 -0
  183. webull/data/common/expiration_cycle.py +26 -0
  184. webull/data/common/instrument_status.py +23 -0
  185. webull/data/common/option_type.py +20 -0
  186. webull/data/common/subscribe_type.py +22 -0
  187. webull/data/common/timespan.py +29 -0
  188. webull/data/data_client.py +35 -0
  189. webull/data/data_streaming_client.py +89 -0
  190. webull/data/internal/__init__.py +0 -0
  191. webull/data/internal/default_retry_policy.py +84 -0
  192. webull/data/internal/exceptions.py +60 -0
  193. webull/data/internal/quotes_client.py +314 -0
  194. webull/data/internal/quotes_decoder.py +40 -0
  195. webull/data/internal/quotes_payload_decoder.py +35 -0
  196. webull/data/internal/quotes_topic.py +36 -0
  197. webull/data/quotes/__init__.py +0 -0
  198. webull/data/quotes/instrument.py +33 -0
  199. webull/data/quotes/market_data.py +187 -0
  200. webull/data/quotes/market_streaming_data.py +66 -0
  201. webull/data/quotes/subscribe/__init__.py +0 -0
  202. webull/data/quotes/subscribe/ask_bid_result.py +49 -0
  203. webull/data/quotes/subscribe/basic_result.py +45 -0
  204. webull/data/quotes/subscribe/broker_result.py +33 -0
  205. webull/data/quotes/subscribe/message_pb2.py +37 -0
  206. webull/data/quotes/subscribe/order_result.py +30 -0
  207. webull/data/quotes/subscribe/payload_type.py +19 -0
  208. webull/data/quotes/subscribe/quote_decoder.py +28 -0
  209. webull/data/quotes/subscribe/quote_result.py +47 -0
  210. webull/data/quotes/subscribe/snapshot_decoder.py +30 -0
  211. webull/data/quotes/subscribe/snapshot_result.py +69 -0
  212. webull/data/quotes/subscribe/tick_decoder.py +29 -0
  213. webull/data/quotes/subscribe/tick_result.py +47 -0
  214. webull/data/request/__init__.py +0 -0
  215. webull/data/request/get_batch_historical_bars_request.py +43 -0
  216. webull/data/request/get_corp_action_request.py +47 -0
  217. webull/data/request/get_eod_bars_request.py +32 -0
  218. webull/data/request/get_historical_bars_request.py +43 -0
  219. webull/data/request/get_instruments_request.py +30 -0
  220. webull/data/request/get_quotes_request.py +35 -0
  221. webull/data/request/get_snapshot_request.py +38 -0
  222. webull/data/request/get_tick_request.py +37 -0
  223. webull/data/request/subscribe_request.py +43 -0
  224. webull/data/request/unsubscribe_request.py +42 -0
  225. webull/trade/__init__.py +2 -0
  226. webull/trade/common/__init__.py +0 -0
  227. webull/trade/common/account_type.py +22 -0
  228. webull/trade/common/category.py +29 -0
  229. webull/trade/common/combo_ticker_type.py +23 -0
  230. webull/trade/common/combo_type.py +31 -0
  231. webull/trade/common/currency.py +24 -0
  232. webull/trade/common/forbid_reason.py +27 -0
  233. webull/trade/common/instrument_type.py +27 -0
  234. webull/trade/common/markets.py +27 -0
  235. webull/trade/common/order_entrust_type.py +21 -0
  236. webull/trade/common/order_side.py +23 -0
  237. webull/trade/common/order_status.py +25 -0
  238. webull/trade/common/order_tif.py +24 -0
  239. webull/trade/common/order_type.py +30 -0
  240. webull/trade/common/trade_policy.py +22 -0
  241. webull/trade/common/trading_date_type.py +24 -0
  242. webull/trade/common/trailing_type.py +23 -0
  243. webull/trade/events/__init__.py +0 -0
  244. webull/trade/events/default_retry_policy.py +64 -0
  245. webull/trade/events/events_pb2.py +43 -0
  246. webull/trade/events/events_pb2_grpc.py +66 -0
  247. webull/trade/events/signature_composer.py +61 -0
  248. webull/trade/events/types.py +21 -0
  249. webull/trade/request/__init__.py +0 -0
  250. webull/trade/request/cancel_order_request.py +28 -0
  251. webull/trade/request/get_account_balance_request.py +28 -0
  252. webull/trade/request/get_account_positions_request.py +30 -0
  253. webull/trade/request/get_account_profile_request.py +26 -0
  254. webull/trade/request/get_app_subscriptions.py +28 -0
  255. webull/trade/request/get_open_orders_request.py +30 -0
  256. webull/trade/request/get_order_detail_request.py +27 -0
  257. webull/trade/request/get_today_orders_request.py +31 -0
  258. webull/trade/request/get_trade_calendar_request.py +30 -0
  259. webull/trade/request/get_trade_instrument_detail_request.py +24 -0
  260. webull/trade/request/get_trade_security_detail_request.py +42 -0
  261. webull/trade/request/get_tradeable_instruments_request.py +27 -0
  262. webull/trade/request/palce_order_request.py +91 -0
  263. webull/trade/request/place_order_request_v2.py +58 -0
  264. webull/trade/request/replace_order_request.py +73 -0
  265. webull/trade/request/replace_order_request_v2.py +38 -0
  266. webull/trade/request/v2/__init__.py +0 -0
  267. webull/trade/request/v2/cancel_option_request.py +28 -0
  268. webull/trade/request/v2/cancel_order_request.py +28 -0
  269. webull/trade/request/v2/get_account_balance_request.py +28 -0
  270. webull/trade/request/v2/get_account_list.py +23 -0
  271. webull/trade/request/v2/get_account_positions_request.py +24 -0
  272. webull/trade/request/v2/get_order_detail_request.py +26 -0
  273. webull/trade/request/v2/get_order_history_request.py +35 -0
  274. webull/trade/request/v2/palce_order_request.py +87 -0
  275. webull/trade/request/v2/place_option_request.py +64 -0
  276. webull/trade/request/v2/preview_option_request.py +28 -0
  277. webull/trade/request/v2/preview_order_request.py +59 -0
  278. webull/trade/request/v2/replace_option_request.py +28 -0
  279. webull/trade/request/v2/replace_order_request.py +57 -0
  280. webull/trade/trade/__init__.py +0 -0
  281. webull/trade/trade/account_info.py +83 -0
  282. webull/trade/trade/order_operation.py +246 -0
  283. webull/trade/trade/trade_calendar.py +37 -0
  284. webull/trade/trade/trade_instrument.py +72 -0
  285. webull/trade/trade/v2/__init__.py +0 -0
  286. webull/trade/trade/v2/account_info_v2.py +55 -0
  287. webull/trade/trade/v2/order_operation_v2.py +206 -0
  288. webull/trade/trade_client.py +43 -0
  289. webull/trade/trade_events_client.py +233 -0
  290. webull_openapi_python_sdk-1.0.0.dist-info/METADATA +28 -0
  291. webull_openapi_python_sdk-1.0.0.dist-info/RECORD +295 -0
  292. webull_openapi_python_sdk-1.0.0.dist-info/WHEEL +5 -0
  293. webull_openapi_python_sdk-1.0.0.dist-info/licenses/LICENSE +202 -0
  294. webull_openapi_python_sdk-1.0.0.dist-info/licenses/NOTICE +56 -0
  295. webull_openapi_python_sdk-1.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,68 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import absolute_import
16
+ # For backwards compatibility, provide imports that used to be here.
17
+ from .connection import is_connection_dropped
18
+ from .request import make_headers
19
+ from .response import is_fp_closed
20
+ from .ssl_ import (
21
+ SSLContext,
22
+ HAS_SNI,
23
+ IS_PYOPENSSL,
24
+ IS_SECURETRANSPORT,
25
+ assert_fingerprint,
26
+ resolve_cert_reqs,
27
+ resolve_ssl_version,
28
+ ssl_wrap_socket,
29
+ )
30
+ from .timeout import (
31
+ current_time,
32
+ Timeout,
33
+ )
34
+
35
+ from .retry import Retry
36
+ from .url import (
37
+ get_host,
38
+ parse_url,
39
+ split_first,
40
+ Url,
41
+ )
42
+ from .wait import (
43
+ wait_for_read,
44
+ wait_for_write
45
+ )
46
+
47
+ __all__ = (
48
+ 'HAS_SNI',
49
+ 'IS_PYOPENSSL',
50
+ 'IS_SECURETRANSPORT',
51
+ 'SSLContext',
52
+ 'Retry',
53
+ 'Timeout',
54
+ 'Url',
55
+ 'assert_fingerprint',
56
+ 'current_time',
57
+ 'is_connection_dropped',
58
+ 'is_fp_closed',
59
+ 'get_host',
60
+ 'parse_url',
61
+ 'make_headers',
62
+ 'resolve_cert_reqs',
63
+ 'resolve_ssl_version',
64
+ 'split_first',
65
+ 'ssl_wrap_socket',
66
+ 'wait_for_read',
67
+ 'wait_for_write'
68
+ )
@@ -0,0 +1,148 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import absolute_import
16
+ import socket
17
+ from .wait import NoWayToWaitForSocketError, wait_for_read
18
+ from ..contrib import _appengine_environ
19
+
20
+
21
+ def is_connection_dropped(conn): # Platform-specific
22
+ """
23
+ Returns True if the connection is dropped and should be closed.
24
+
25
+ :param conn:
26
+ :class:`httplib.HTTPConnection` object.
27
+
28
+ Note: For platforms like AppEngine, this will always return ``False`` to
29
+ let the platform handle connection recycling transparently for us.
30
+ """
31
+ sock = getattr(conn, 'sock', False)
32
+ if sock is False: # Platform-specific: AppEngine
33
+ return False
34
+ if sock is None: # Connection already closed (such as by httplib).
35
+ return True
36
+ try:
37
+ # Returns True if readable, which here means it's been dropped
38
+ return wait_for_read(sock, timeout=0.0)
39
+ except NoWayToWaitForSocketError: # Platform-specific: AppEngine
40
+ return False
41
+
42
+
43
+ # This function is copied from socket.py in the Python 2.7 standard
44
+ # library test suite. Added to its signature is only `socket_options`.
45
+ # One additional modification is that we avoid binding to IPv6 servers
46
+ # discovered in DNS if the system doesn't have IPv6 functionality.
47
+ def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
48
+ source_address=None, socket_options=None):
49
+ """Connect to *address* and return the socket object.
50
+
51
+ Convenience function. Connect to *address* (a 2-tuple ``(host,
52
+ port)``) and return the socket object. Passing the optional
53
+ *timeout* parameter will set the timeout on the socket instance
54
+ before attempting to connect. If no *timeout* is supplied, the
55
+ global default timeout setting returned by :func:`getdefaulttimeout`
56
+ is used. If *source_address* is set it must be a tuple of (host, port)
57
+ for the socket to bind as a source address before making the connection.
58
+ An host of '' or port 0 tells the OS to use the default.
59
+ """
60
+
61
+ host, port = address
62
+ if host.startswith('['):
63
+ host = host.strip('[]')
64
+ err = None
65
+
66
+ # Using the value from allowed_gai_family() in the context of getaddrinfo lets
67
+ # us select whether to work with IPv4 DNS records, IPv6 records, or both.
68
+ # The original create_connection function always returns all records.
69
+ family = allowed_gai_family()
70
+
71
+ for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
72
+ af, socktype, proto, canonname, sa = res
73
+ sock = None
74
+ try:
75
+ sock = socket.socket(af, socktype, proto)
76
+
77
+ # If provided, set socket level options before connecting.
78
+ _set_socket_options(sock, socket_options)
79
+
80
+ if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
81
+ sock.settimeout(timeout)
82
+ if source_address:
83
+ sock.bind(source_address)
84
+ sock.connect(sa)
85
+ return sock
86
+
87
+ except socket.error as e:
88
+ err = e
89
+ if sock is not None:
90
+ sock.close()
91
+ sock = None
92
+
93
+ if err is not None:
94
+ raise err
95
+
96
+ raise socket.error("getaddrinfo returns an empty list")
97
+
98
+
99
+ def _set_socket_options(sock, options):
100
+ if options is None:
101
+ return
102
+
103
+ for opt in options:
104
+ sock.setsockopt(*opt)
105
+
106
+
107
+ def allowed_gai_family():
108
+ """This function is designed to work in the context of
109
+ getaddrinfo, where family=socket.AF_UNSPEC is the default and
110
+ will perform a DNS search for both IPv6 and IPv4 records."""
111
+
112
+ family = socket.AF_INET
113
+ if HAS_IPV6:
114
+ family = socket.AF_UNSPEC
115
+ return family
116
+
117
+
118
+ def _has_ipv6(host):
119
+ """ Returns True if the system can bind an IPv6 address. """
120
+ sock = None
121
+ has_ipv6 = False
122
+
123
+ # App Engine doesn't support IPV6 sockets and actually has a quota on the
124
+ # number of sockets that can be used, so just early out here instead of
125
+ # creating a socket needlessly.
126
+ # See https://github.com/urllib3/urllib3/issues/1446
127
+ if _appengine_environ.is_appengine_sandbox():
128
+ return False
129
+
130
+ if socket.has_ipv6:
131
+ # has_ipv6 returns true if cPython was compiled with IPv6 support.
132
+ # It does not tell us if the system has IPv6 support enabled. To
133
+ # determine that we must bind to an IPv6 address.
134
+ # https://github.com/shazow/urllib3/pull/611
135
+ # https://bugs.python.org/issue658327
136
+ try:
137
+ sock = socket.socket(socket.AF_INET6)
138
+ sock.bind((host, 0))
139
+ has_ipv6 = True
140
+ except Exception:
141
+ pass
142
+
143
+ if sock:
144
+ sock.close()
145
+ return has_ipv6
146
+
147
+
148
+ HAS_IPV6 = _has_ipv6('::1')
@@ -0,0 +1,35 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import collections
16
+ from ..packages import six
17
+ from ..packages.six.moves import queue
18
+
19
+ if six.PY2:
20
+ # Queue is imported for side effects on MS Windows. See issue #229.
21
+ import Queue as _unused_module_Queue # noqa: F401
22
+
23
+
24
+ class LifoQueue(queue.Queue):
25
+ def _init(self, _):
26
+ self.queue = collections.deque()
27
+
28
+ def _qsize(self, len=len):
29
+ return len(self.queue)
30
+
31
+ def _put(self, item):
32
+ self.queue.append(item)
33
+
34
+ def _get(self):
35
+ return self.queue.pop()
@@ -0,0 +1,132 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import absolute_import
16
+ from base64 import b64encode
17
+
18
+ from ..packages.six import b, integer_types
19
+ from ..exceptions import UnrewindableBodyError
20
+
21
+ ACCEPT_ENCODING = 'gzip,deflate'
22
+ _FAILEDTELL = object()
23
+
24
+
25
+ def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
26
+ basic_auth=None, proxy_basic_auth=None, disable_cache=None):
27
+ """
28
+ Shortcuts for generating request headers.
29
+
30
+ :param keep_alive:
31
+ If ``True``, adds 'connection: keep-alive' header.
32
+
33
+ :param accept_encoding:
34
+ Can be a boolean, list, or string.
35
+ ``True`` translates to 'gzip,deflate'.
36
+ List will get joined by comma.
37
+ String will be used as provided.
38
+
39
+ :param user_agent:
40
+ String representing the user-agent you want, such as
41
+ "python-urllib3/0.6"
42
+
43
+ :param basic_auth:
44
+ Colon-separated username:password string for 'authorization: basic ...'
45
+ auth header.
46
+
47
+ :param proxy_basic_auth:
48
+ Colon-separated username:password string for 'proxy-authorization: basic ...'
49
+ auth header.
50
+
51
+ :param disable_cache:
52
+ If ``True``, adds 'cache-control: no-cache' header.
53
+
54
+ Example::
55
+
56
+ >>> make_headers(keep_alive=True, user_agent="Batman/1.0")
57
+ {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'}
58
+ >>> make_headers(accept_encoding=True)
59
+ {'accept-encoding': 'gzip,deflate'}
60
+ """
61
+ headers = {}
62
+ if accept_encoding:
63
+ if isinstance(accept_encoding, str):
64
+ pass
65
+ elif isinstance(accept_encoding, list):
66
+ accept_encoding = ','.join(accept_encoding)
67
+ else:
68
+ accept_encoding = ACCEPT_ENCODING
69
+ headers['accept-encoding'] = accept_encoding
70
+
71
+ if user_agent:
72
+ headers['user-agent'] = user_agent
73
+
74
+ if keep_alive:
75
+ headers['connection'] = 'keep-alive'
76
+
77
+ if basic_auth:
78
+ headers['authorization'] = 'Basic ' + \
79
+ b64encode(b(basic_auth)).decode('utf-8')
80
+
81
+ if proxy_basic_auth:
82
+ headers['proxy-authorization'] = 'Basic ' + \
83
+ b64encode(b(proxy_basic_auth)).decode('utf-8')
84
+
85
+ if disable_cache:
86
+ headers['cache-control'] = 'no-cache'
87
+
88
+ return headers
89
+
90
+
91
+ def set_file_position(body, pos):
92
+ """
93
+ If a position is provided, move file to that point.
94
+ Otherwise, we'll attempt to record a position for future use.
95
+ """
96
+ if pos is not None:
97
+ rewind_body(body, pos)
98
+ elif getattr(body, 'tell', None) is not None:
99
+ try:
100
+ pos = body.tell()
101
+ except (IOError, OSError):
102
+ # This differentiates from None, allowing us to catch
103
+ # a failed `tell()` later when trying to rewind the body.
104
+ pos = _FAILEDTELL
105
+
106
+ return pos
107
+
108
+
109
+ def rewind_body(body, body_pos):
110
+ """
111
+ Attempt to rewind body to a certain position.
112
+ Primarily used for request redirects and retries.
113
+
114
+ :param body:
115
+ File-like object that supports seek.
116
+
117
+ :param int pos:
118
+ Position to seek to in file.
119
+ """
120
+ body_seek = getattr(body, 'seek', None)
121
+ if body_seek is not None and isinstance(body_pos, integer_types):
122
+ try:
123
+ body_seek(body_pos)
124
+ except (IOError, OSError):
125
+ raise UnrewindableBodyError("An error occurred when rewinding request "
126
+ "body for redirect/retry.")
127
+ elif body_pos is _FAILEDTELL:
128
+ raise UnrewindableBodyError("Unable to record file position for rewinding "
129
+ "request body during a redirect/retry.")
130
+ else:
131
+ raise ValueError("body_pos must be of type integer, "
132
+ "instead it was %s." % type(body_pos))
@@ -0,0 +1,101 @@
1
+ # Copyright 2022 Webull
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import absolute_import
16
+ from ..packages.six.moves import http_client as httplib
17
+
18
+ from ..exceptions import HeaderParsingError
19
+
20
+
21
+ def is_fp_closed(obj):
22
+ """
23
+ Checks whether a given file-like object is closed.
24
+
25
+ :param obj:
26
+ The file-like object to check.
27
+ """
28
+
29
+ try:
30
+ # Check `isclosed()` first, in case Python3 doesn't set `closed`.
31
+ # GH Issue #928
32
+ return obj.isclosed()
33
+ except AttributeError:
34
+ pass
35
+
36
+ try:
37
+ # Check via the official file-like-object way.
38
+ return obj.closed
39
+ except AttributeError:
40
+ pass
41
+
42
+ try:
43
+ # Check if the object is a container for another file-like object that
44
+ # gets released on exhaustion (e.g. HTTPResponse).
45
+ return obj.fp is None
46
+ except AttributeError:
47
+ pass
48
+
49
+ raise ValueError("Unable to determine whether fp is closed.")
50
+
51
+
52
+ def assert_header_parsing(headers):
53
+ """
54
+ Asserts whether all headers have been successfully parsed.
55
+ Extracts encountered errors from the result of parsing headers.
56
+
57
+ Only works on Python 3.
58
+
59
+ :param headers: Headers to verify.
60
+ :type headers: `httplib.HTTPMessage`.
61
+
62
+ :raises urllib3.exceptions.HeaderParsingError:
63
+ If parsing errors are found.
64
+ """
65
+
66
+ # This will fail silently if we pass in the wrong kind of parameter.
67
+ # To make debugging easier add an explicit check.
68
+ if not isinstance(headers, httplib.HTTPMessage):
69
+ raise TypeError('expected httplib.Message, got {0}.'.format(
70
+ type(headers)))
71
+
72
+ defects = getattr(headers, 'defects', None)
73
+ get_payload = getattr(headers, 'get_payload', None)
74
+
75
+ unparsed_data = None
76
+ if get_payload:
77
+ # get_payload is actually email.message.Message.get_payload;
78
+ # we're only interested in the result if it's not a multipart message
79
+ if not headers.is_multipart():
80
+ payload = get_payload()
81
+
82
+ if isinstance(payload, (bytes, str)):
83
+ unparsed_data = payload
84
+
85
+ if defects or unparsed_data:
86
+ raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
87
+
88
+
89
+ def is_response_to_head(response):
90
+ """
91
+ Checks whether the request of a response has been a HEAD-request.
92
+ Handles the quirks of AppEngine.
93
+
94
+ :param conn:
95
+ :type conn: :class:`httplib.HTTPResponse`
96
+ """
97
+ # FIXME: Can we do this somehow without accessing private httplib _method?
98
+ method = response._method
99
+ if isinstance(method, int): # Platform-specific: Appengine
100
+ return method == 3
101
+ return method.upper() == 'HEAD'