python-httpfile 0.0.3__py3-none-any.whl → 0.0.4.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.
httpfile/__init__.py CHANGED
@@ -4,14 +4,15 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
7
- __version__ = (0, 0, 3)
7
+ __version__ = (0, 0, 4)
8
8
  __all__ = ["HTTPFileReader", "AsyncHTTPFileReader"]
9
9
 
10
10
  import errno
11
11
 
12
12
  from collections.abc import Awaitable, Callable, Mapping
13
13
  from functools import cached_property, partial
14
- from inspect import isawaitable, signature
14
+ from importlib.util import find_spec
15
+ from inspect import isawaitable
15
16
  from io import (
16
17
  BufferedReader, RawIOBase, TextIOWrapper, UnsupportedOperation, DEFAULT_BUFFER_SIZE,
17
18
  )
@@ -19,7 +20,7 @@ from os import fstat, stat, PathLike
19
20
  from shutil import COPY_BUFSIZE # type: ignore
20
21
  from sys import exc_info
21
22
  from typing import cast, overload, Any, BinaryIO, Literal, Self
22
- from types import MappingProxyType, MethodType
23
+ from types import MappingProxyType
23
24
  from warnings import warn
24
25
 
25
26
  from asynctools import ensure_async, run_async
@@ -102,7 +103,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
102
103
  # NOTE: If the offset of the forward seek is not higher than this value,
103
104
  # it will be directly read and discarded, default to 1 MB
104
105
  seek_threshold: int = 1 << 20,
105
- urlopen: Callable = urlopen,
106
+ urlopen = urlopen,
106
107
  ):
107
108
  if headers:
108
109
  headers = {**headers, "Accept-Encoding": "identity"}
@@ -112,6 +113,8 @@ class HTTPFileReader(RawIOBase, BinaryIO):
112
113
  headers["Range"] = f"bytes={start}-"
113
114
  elif start < 0:
114
115
  headers["Range"] = f"bytes={start}"
116
+ if urlopen is None:
117
+ urlopen = globals()["urlopen"]
115
118
  if callable(url):
116
119
  geturl = url
117
120
  def url():
@@ -250,7 +253,16 @@ class HTTPFileReader(RawIOBase, BinaryIO):
250
253
  return 0
251
254
  if self.file_closed:
252
255
  self.reconnect()
253
- size = self.file.readinto(buffer)
256
+ try:
257
+ readinto = self.file.readinto
258
+ except AttributeError:
259
+ read = self.file.read
260
+ def readinto(buffer, /):
261
+ data = read(len(buffer))
262
+ size = len(data)
263
+ buffer[:size] = data
264
+ return data
265
+ size = readinto(buffer)
254
266
  if size:
255
267
  self._add_start(size)
256
268
  return size
@@ -262,6 +274,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
262
274
  return b""
263
275
  if self.file_closed:
264
276
  self.reconnect()
277
+ # TODO: if no readline method, give a default impl
265
278
  if size is None or size < 0:
266
279
  data = self.file.readline()
267
280
  else:
@@ -277,6 +290,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
277
290
  return []
278
291
  if self.file_closed:
279
292
  self.reconnect()
293
+ # TODO: if no readlines method, give a default impl
280
294
  ls = self.file.readlines(hint)
281
295
  if ls:
282
296
  self._add_start(sum(map(len, ls)))
@@ -384,7 +398,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
384
398
  headers: None | Mapping = None,
385
399
  start: int = 0,
386
400
  seek_threshold: int = 1 << 20,
387
- urlopen: Callable = urlopen,
401
+ urlopen = None,
388
402
  ) -> Self | BufferedReader:
389
403
  ...
390
404
  @overload
@@ -402,7 +416,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
402
416
  headers: None | Mapping = None,
403
417
  start: int = 0,
404
418
  seek_threshold: int = 1 << 20,
405
- urlopen: Callable = urlopen,
419
+ urlopen = None,
406
420
  ) -> TextIOWrapper:
407
421
  ...
408
422
  @classmethod
@@ -419,7 +433,7 @@ class HTTPFileReader(RawIOBase, BinaryIO):
419
433
  headers: None | Mapping = None,
420
434
  start: int = 0,
421
435
  seek_threshold: int = 1 << 20,
422
- urlopen: Callable = urlopen,
436
+ urlopen = None,
423
437
  ) -> Self | BufferedReader | TextIOWrapper:
424
438
  file = cls(
425
439
  url=url,
@@ -517,9 +531,9 @@ class AsyncHTTPFileReader(HTTPFileReader):
517
531
  headers: None | Mapping = None,
518
532
  start: int = 0,
519
533
  seek_threshold: int = 1 << 20,
520
- urlopen: Callable = urlopen,
534
+ urlopen = None,
521
535
  ):
522
- run_async(self._init(
536
+ run_async(self.__ainit__(
523
537
  url=url,
524
538
  headers=headers,
525
539
  start=start,
@@ -542,7 +556,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
542
556
  else:
543
557
  raise StopAsyncIteration
544
558
 
545
- async def _init(
559
+ async def __ainit__(
546
560
  self,
547
561
  /,
548
562
  url: str | Callable[[], str] | Callable[[], Awaitable[str]],
@@ -551,8 +565,6 @@ class AsyncHTTPFileReader(HTTPFileReader):
551
565
  seek_threshold: int = 1 << 20,
552
566
  urlopen = None,
553
567
  ):
554
- if urlopen is None:
555
- urlopen = signature(type(self).__init__).parameters["urlopen"].default
556
568
  if headers:
557
569
  headers = {**headers, "Accept-Encoding": "identity"}
558
570
  else:
@@ -561,6 +573,8 @@ class AsyncHTTPFileReader(HTTPFileReader):
561
573
  headers["Range"] = f"bytes={start}-"
562
574
  elif start < 0:
563
575
  headers["Range"] = f"bytes={start}"
576
+ if urlopen is None:
577
+ urlopen = globals()["urlopen"]
564
578
  if callable(url):
565
579
  geturl = url
566
580
  async def url() -> str:
@@ -628,10 +642,11 @@ class AsyncHTTPFileReader(HTTPFileReader):
628
642
  return b""
629
643
  if self.file_closed:
630
644
  await self.reconnect()
645
+ read = ensure_async(self.file.read, threaded=True)
631
646
  if size is None or size < 0:
632
- data = await ensure_async(self.file.read, threaded=True)()
647
+ data = await read(-1)
633
648
  else:
634
- data = await ensure_async(self.file.read, threaded=True)(size)
649
+ data = await read(size)
635
650
  if data:
636
651
  self._add_start(len(data))
637
652
  return data
@@ -643,7 +658,16 @@ class AsyncHTTPFileReader(HTTPFileReader):
643
658
  return 0
644
659
  if self.file_closed:
645
660
  await self.reconnect()
646
- size = await ensure_async(self.file.readinto, threaded=True)(buffer)
661
+ try:
662
+ readinto = ensure_async(self.file.readinto, threaded=True)
663
+ except AttributeError:
664
+ read = ensure_async(self.file.read, threaded=True)
665
+ async def readinto(buffer, /):
666
+ data = await read(len(buffer))
667
+ size = len(data)
668
+ buffer[:size] = data
669
+ return size
670
+ size = await readinto(buffer)
647
671
  if size:
648
672
  self._add_start(size)
649
673
  return size
@@ -655,6 +679,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
655
679
  return b""
656
680
  if self.file_closed:
657
681
  await self.reconnect()
682
+ # TODO: if no readline method, give a default impl
658
683
  if size is None or size < 0:
659
684
  data = await ensure_async(self.file.readline, threaded=True)()
660
685
  else:
@@ -670,6 +695,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
670
695
  return []
671
696
  if self.file_closed:
672
697
  await self.reconnect()
698
+ # TODO: if no readlines method, give a default impl
673
699
  ls = await ensure_async(self.file.readlines, threaded=True)(hint)
674
700
  if ls:
675
701
  self._add_start(sum(map(len, ls)))
@@ -749,7 +775,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
749
775
  urlopen = None,
750
776
  ) -> Self: # type: ignore
751
777
  self = cls.__new__(cls)
752
- await self._init(
778
+ await self.__ainit__(
753
779
  url=url,
754
780
  headers=headers,
755
781
  start=start,
@@ -773,7 +799,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
773
799
  headers: None | Mapping = None,
774
800
  start: int = 0,
775
801
  seek_threshold: int = 1 << 20,
776
- urlopen: Callable = urlopen,
802
+ urlopen = None,
777
803
  ) -> Self | AsyncBufferedReader:
778
804
  ...
779
805
  @overload
@@ -791,7 +817,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
791
817
  headers: None | Mapping = None,
792
818
  start: int = 0,
793
819
  seek_threshold: int = 1 << 20,
794
- urlopen: Callable = urlopen,
820
+ urlopen = None,
795
821
  ) -> AsyncTextIOWrapper:
796
822
  ...
797
823
  @classmethod
@@ -807,7 +833,7 @@ class AsyncHTTPFileReader(HTTPFileReader):
807
833
  headers: None | Mapping = None,
808
834
  start: int = 0,
809
835
  seek_threshold: int = 1 << 20,
810
- urlopen: Callable = urlopen,
836
+ urlopen = None,
811
837
  ) -> Self | AsyncBufferedReader | AsyncTextIOWrapper:
812
838
  file = await cls.new(
813
839
  url=url,
@@ -895,10 +921,10 @@ class AsyncHTTPFileReader(HTTPFileReader):
895
921
  return buffer
896
922
 
897
923
 
898
- try:
924
+ if find_spec("urllib3"):
899
925
  from urllib.error import HTTPError
900
- from urllib3 import request as urllib3_request
901
- from urllib3.poolmanager import PoolManager
926
+
927
+ _urllib3_urlopen = None
902
928
 
903
929
  class Urllib3FileReader(HTTPFileReader):
904
930
 
@@ -909,17 +935,28 @@ try:
909
935
  headers: None | Mapping = None,
910
936
  start: int = 0,
911
937
  seek_threshold: int = 1 << 20,
912
- urlopen = partial(urllib3_request, "GET"), # type: ignore
938
+ urlopen = None,
913
939
  ):
940
+ global _urllib3_urlopen
941
+ from urllib3 import request
942
+ from urllib3.poolmanager import PoolManager
943
+
914
944
  if isinstance(urlopen, PoolManager):
915
945
  urlopen = partial(urlopen.request, "GET", preload_content=False)
946
+ elif urlopen is None:
947
+ if _urllib3_urlopen is None:
948
+ urlopen = _urllib3_urlopen = partial(cast(Callable, request), "GET", preload_content=False)
949
+ else:
950
+ urlopen = _urllib3_urlopen
916
951
  else:
917
952
  urlopen = partial(urlopen, preload_content=False)
953
+
918
954
  def urlopen_wrapper(url: str, headers: None | Mapping = headers):
919
955
  resp = urlopen(url, headers=headers)
920
956
  if resp.status >= 400:
921
957
  raise HTTPError(resp.url, resp.status, resp.reason, resp.headers, resp)
922
958
  return resp
959
+
923
960
  super().__init__(
924
961
  url,
925
962
  headers=headers,
@@ -929,15 +966,10 @@ try:
929
966
  )
930
967
 
931
968
  __all__.append("Urllib3FileReader")
932
- except ImportError:
933
- pass
934
969
 
935
970
 
936
- try:
937
- from requests import request as requests_request, Session
938
-
939
- if "__del__" not in Session.__dict__:
940
- setattr(Session, "__del__", lambda self, /: self.close())
971
+ if find_spec("requests"):
972
+ _requests_urlopen = None
941
973
 
942
974
  class RequestsFileReader(HTTPFileReader):
943
975
 
@@ -948,10 +980,19 @@ try:
948
980
  headers: None | Mapping = None,
949
981
  start: int = 0,
950
982
  seek_threshold: int = 1 << 20,
951
- urlopen = partial(requests_request, "GET"),
983
+ urlopen = None,
952
984
  ):
985
+ global _requests_urlopen
986
+ from requests import request, Session
953
987
  if isinstance(urlopen, Session):
954
988
  urlopen = partial(urlopen.request, "GET", stream=True)
989
+ elif urlopen is None:
990
+ if _requests_urlopen is None:
991
+ if "__del__" not in Session.__dict__:
992
+ setattr(Session, "__del__", lambda self, /: self.close())
993
+ urlopen = _requests_urlopen = partial(request, "GET", stream=True)
994
+ else:
995
+ urlopen = _requests_urlopen
955
996
  else:
956
997
  urlopen = partial(urlopen, stream=True)
957
998
  def urlopen_wrapper(url: str, headers: None | Mapping = headers):
@@ -971,33 +1012,16 @@ try:
971
1012
  return self.response.raw
972
1013
 
973
1014
  __all__.append("RequestsFileReader")
974
- except ImportError:
975
- pass
976
1015
 
977
1016
 
978
- try:
979
- from aiohttp import request as aiohttp_request, ClientSession
1017
+ if find_spec("aiohttp"):
1018
+ from types import MethodType
980
1019
 
981
- class AiohttpFileReader(AsyncHTTPFileReader):
1020
+ _aiohttp_urlopen = None
982
1021
 
983
- def __init__(
984
- self,
985
- /,
986
- url: str | Callable[[], str] | Callable[[], Awaitable[str]],
987
- headers: None | Mapping = None,
988
- start: int = 0,
989
- seek_threshold: int = 1 << 20,
990
- urlopen = partial(aiohttp_request, "GET"),
991
- ):
992
- super().__init__(
993
- url=url,
994
- headers=headers,
995
- start=start,
996
- seek_threshold=seek_threshold,
997
- urlopen=urlopen,
998
- )
1022
+ class AiohttpFileReader(AsyncHTTPFileReader):
999
1023
 
1000
- async def _init(
1024
+ async def __ainit__(
1001
1025
  self,
1002
1026
  /,
1003
1027
  url: str | Callable[[], str] | Callable[[], Awaitable[str]],
@@ -1006,17 +1030,26 @@ try:
1006
1030
  seek_threshold: int = 1 << 20,
1007
1031
  urlopen = None,
1008
1032
  ):
1009
- if urlopen is None:
1010
- urlopen = signature(type(self).__init__).parameters["urlopen"].default
1033
+ global _aiohttp_urlopen
1034
+ from aiohttp import request, ClientSession
1035
+
1011
1036
  close_session = True
1012
1037
  if isinstance(urlopen, ClientSession):
1013
1038
  urlopen = urlopen.get
1014
- do_not_close_session = False
1015
- if close_session:
1039
+ close_session = False
1040
+ if urlopen is None:
1041
+ if _aiohttp_urlopen is None:
1042
+ urlopen = _aiohttp_urlopen = partial(request, "GET")
1043
+ else:
1044
+ urlopen = _aiohttp_urlopen
1045
+ else:
1016
1046
  func = urlopen
1017
1047
  if isinstance(func, partial):
1018
1048
  func = func.func
1019
- close_session = not (isinstance(func, MethodType) and isinstance(func.__self__, ClientSession))
1049
+ close_session = not (
1050
+ isinstance(func, MethodType) and
1051
+ isinstance(func.__self__, ClientSession)
1052
+ )
1020
1053
  async def urlopen_wrapper(url: str, headers: None | Mapping = headers):
1021
1054
  resp = await urlopen(url, headers=headers).__aenter__()
1022
1055
  async def aclose():
@@ -1029,7 +1062,7 @@ try:
1029
1062
  resp.aclose = aclose
1030
1063
  resp.raise_for_status()
1031
1064
  return resp
1032
- await super()._init(
1065
+ await super().__ainit__(
1033
1066
  url=url,
1034
1067
  headers=headers,
1035
1068
  start=start,
@@ -1046,60 +1079,13 @@ try:
1046
1079
  return self.response.closed
1047
1080
 
1048
1081
  __all__.append("AiohttpFileReader")
1049
- except ImportError:
1050
- pass
1051
1082
 
1052
1083
 
1053
- try:
1054
- from contextlib import asynccontextmanager
1084
+ if find_spec("httpx"):
1055
1085
  from filewrap import bytes_iter_to_reader, bytes_iter_to_async_reader
1056
- from httpx import stream, Client, AsyncClient
1057
-
1058
- if "__del__" not in Client.__dict__:
1059
- setattr(Client, "__del__", lambda self: self.close())
1060
- if "__del__" not in AsyncClient.__dict__:
1061
- setattr(AsyncClient, "__del__", lambda self: run_async(self.aclose()))
1062
-
1063
- def async_stream(
1064
- method,
1065
- url,
1066
- params = None,
1067
- content = None,
1068
- data = None,
1069
- files = None,
1070
- json = None,
1071
- headers = None,
1072
- cookies = None,
1073
- auth = None,
1074
- proxy = None,
1075
- proxies = None,
1076
- timeout = 5.0,
1077
- follow_redirects = False,
1078
- verify = True,
1079
- cert = None,
1080
- trust_env = True,
1081
- ):
1082
- client = AsyncClient(
1083
- cookies=cookies,
1084
- proxy=proxy,
1085
- proxies=proxies,
1086
- cert=cert,
1087
- verify=verify,
1088
- timeout=timeout,
1089
- trust_env=trust_env,
1090
- )
1091
- return client.stream(
1092
- method=method,
1093
- url=url,
1094
- content=content,
1095
- data=data,
1096
- files=files,
1097
- json=json,
1098
- params=params,
1099
- headers=headers,
1100
- auth=auth,
1101
- follow_redirects=follow_redirects,
1102
- )
1086
+
1087
+ _httpx_urlopen = None
1088
+ _httpx_urlopen_async = None
1103
1089
 
1104
1090
  class HttpxFileReader(HTTPFileReader):
1105
1091
 
@@ -1110,10 +1096,21 @@ try:
1110
1096
  headers: None | Mapping = None,
1111
1097
  start: int = 0,
1112
1098
  seek_threshold: int = 1 << 20,
1113
- urlopen = partial(stream, "GET"),
1099
+ urlopen = None,
1114
1100
  ):
1101
+ global _httpx_urlopen
1102
+ from httpx import stream, Client
1103
+
1115
1104
  if isinstance(urlopen, Client):
1116
1105
  urlopen = partial(urlopen.stream, "GET")
1106
+ elif urlopen is None:
1107
+ if _httpx_urlopen is None:
1108
+ if "__del__" not in Client.__dict__:
1109
+ setattr(Client, "__del__", lambda self: self.close())
1110
+ urlopen = _httpx_urlopen = partial(stream, "GET")
1111
+ else:
1112
+ urlopen = _httpx_urlopen
1113
+
1117
1114
  def urlopen_wrapper(url: str, headers: None | Mapping = headers):
1118
1115
  context = urlopen(url, headers=headers)
1119
1116
  resp = context.__enter__()
@@ -1122,6 +1119,7 @@ try:
1122
1119
  file = bytes_iter_to_reader(resp.iter_raw())
1123
1120
  self.__dict__["file"] = file
1124
1121
  return resp
1122
+
1125
1123
  super().__init__(
1126
1124
  url,
1127
1125
  headers=headers,
@@ -1136,24 +1134,7 @@ try:
1136
1134
 
1137
1135
  class AsyncHttpxFileReader(AsyncHTTPFileReader):
1138
1136
 
1139
- def __init__(
1140
- self,
1141
- /,
1142
- url: str | Callable[[], str] | Callable[[], Awaitable[str]],
1143
- headers: None | Mapping = None,
1144
- start: int = 0,
1145
- seek_threshold: int = 1 << 20,
1146
- urlopen = partial(async_stream, "GET"),
1147
- ):
1148
- super().__init__(
1149
- url=url,
1150
- headers=headers,
1151
- start=start,
1152
- seek_threshold=seek_threshold,
1153
- urlopen=urlopen,
1154
- )
1155
-
1156
- async def _init(
1137
+ async def __ainit__(
1157
1138
  self,
1158
1139
  /,
1159
1140
  url: str | Callable[[], str] | Callable[[], Awaitable[str]],
@@ -1162,10 +1143,59 @@ try:
1162
1143
  seek_threshold: int = 1 << 20,
1163
1144
  urlopen = None,
1164
1145
  ):
1165
- if urlopen is None:
1166
- urlopen = signature(type(self).__init__).parameters["urlopen"].default
1146
+ global _httpx_urlopen_async
1147
+ from httpx import AsyncClient
1148
+
1167
1149
  if isinstance(urlopen, AsyncClient):
1168
1150
  urlopen = partial(urlopen.stream, "GET")
1151
+ elif urlopen is None:
1152
+ if _httpx_urlopen_async is None:
1153
+ if "__del__" not in AsyncClient.__dict__:
1154
+ setattr(AsyncClient, "__del__", lambda self: run_async(self.aclose()))
1155
+ def async_stream(
1156
+ method,
1157
+ url,
1158
+ params = None,
1159
+ content = None,
1160
+ data = None,
1161
+ files = None,
1162
+ json = None,
1163
+ headers = None,
1164
+ cookies = None,
1165
+ auth = None,
1166
+ proxy = None,
1167
+ proxies = None,
1168
+ timeout = 5.0,
1169
+ follow_redirects = False,
1170
+ verify = True,
1171
+ cert = None,
1172
+ trust_env = True,
1173
+ ):
1174
+ client = AsyncClient(
1175
+ cookies=cookies,
1176
+ proxy=proxy,
1177
+ proxies=proxies,
1178
+ cert=cert,
1179
+ verify=verify,
1180
+ timeout=timeout,
1181
+ trust_env=trust_env,
1182
+ )
1183
+ return client.stream(
1184
+ method=method,
1185
+ url=url,
1186
+ content=content,
1187
+ data=data,
1188
+ files=files,
1189
+ json=json,
1190
+ params=params,
1191
+ headers=headers,
1192
+ auth=auth,
1193
+ follow_redirects=follow_redirects,
1194
+ )
1195
+ urlopen = _httpx_urlopen_async = partial(async_stream, "GET")
1196
+ else:
1197
+ urlopen = _httpx_urlopen_async
1198
+
1169
1199
  async def urlopen_wrapper(url: str, headers: None | Mapping = headers):
1170
1200
  context = urlopen(url, headers=headers)
1171
1201
  resp = await context.__aenter__()
@@ -1174,7 +1204,8 @@ try:
1174
1204
  file = bytes_iter_to_async_reader(resp.aiter_raw())
1175
1205
  self.__dict__["file"] = file
1176
1206
  return resp
1177
- await super()._init(
1207
+
1208
+ await super().__ainit__(
1178
1209
  url=url,
1179
1210
  headers=headers,
1180
1211
  start=start,
@@ -1188,7 +1219,6 @@ try:
1188
1219
 
1189
1220
  __all__.append("HttpxFileReader")
1190
1221
  __all__.append("AsyncHttpxFileReader")
1191
- except ImportError:
1192
- pass
1193
1222
 
1223
+ # TODO: 增加 blacksheep 的 HTTPFileReader
1194
1224
  # TODO: 设计实现一个 HTTPFileWriter,用于实现上传,关闭后视为上传完成
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-httpfile
3
- Version: 0.0.3
3
+ Version: 0.0.4.1
4
4
  Summary: Python httpfile.
5
5
  Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-httpfile
6
6
  License: MIT
@@ -25,7 +25,7 @@ Requires-Dist: http_response
25
25
  Requires-Dist: python-asynctools (>=0.0.5)
26
26
  Requires-Dist: python-filewrap (>=0.2.1)
27
27
  Requires-Dist: python-property (>=0.0.2)
28
- Requires-Dist: python-urlopen (>=0.0.7)
28
+ Requires-Dist: python-urlopen (>=0.0.7.1)
29
29
  Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-httpfile
30
30
  Description-Content-Type: text/markdown
31
31
 
@@ -0,0 +1,7 @@
1
+ LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
+ httpfile/__init__.py,sha256=ffww3j6Gk2dFLSy18a1PlRlT-yez5V857HbZp080Bxs,39533
3
+ httpfile/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_httpfile-0.0.4.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
+ python_httpfile-0.0.4.1.dist-info/METADATA,sha256=XreyhqBNvwXua7uaRsVBHkf88xLuhhi2Vmd4UAe5eEk,1522
6
+ python_httpfile-0.0.4.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
7
+ python_httpfile-0.0.4.1.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
- httpfile/__init__.py,sha256=Cp1mdmn7hLNIUsvScclByZZC0hNZh-ggljiYFH1PLVU,37815
3
- httpfile/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_httpfile-0.0.3.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
- python_httpfile-0.0.3.dist-info/METADATA,sha256=5a1WYcujAY1_K8zdnseHhqzSjrUSPaw_a8sc78kR3lM,1518
6
- python_httpfile-0.0.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
7
- python_httpfile-0.0.3.dist-info/RECORD,,