Skip to content

Commit f11f583

Browse files
committed
mystbin 4 commit
1 parent 038f655 commit f11f583

11 files changed

+441
-549
lines changed

.github/dependabot.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

CHANGELOG.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
6.1.0
1+
7.0.0
22

33
# mystbin.py Changelog
44

55
## Added
66

77
## Changes
8-
- Modernise codebase and tooling with Ruff.
8+
- Codebase now aligns with new mystbin.
99

1010
## Fixes
11-
- KeyError upon accessing late init key in api response.
1211

1312
### Notes

mystbin/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
DEALINGS IN THE SOFTWARE.
2323
"""
2424

25-
__version__ = "6.1.0"
25+
__version__ = "7.0.0"
2626

2727
from typing import Literal, NamedTuple
2828

@@ -39,4 +39,6 @@ class VersionInfo(NamedTuple):
3939
serial: int
4040

4141

42-
version_info: VersionInfo = VersionInfo(major=6, minor=1, micro=0, releaselevel="final", serial=0)
42+
version_info: VersionInfo = VersionInfo(major=7, minor=0, micro=0, releaselevel="final", serial=0)
43+
44+
del NamedTuple, Literal, VersionInfo

mystbin/client.py

+15-124
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
from .http import HTTPClient
2828
from .paste import File, Paste
29-
from .utils import require_authentication
3029

3130
if TYPE_CHECKING:
3231
import datetime
@@ -41,17 +40,14 @@
4140
class Client:
4241
__slots__ = ("http",)
4342

44-
def __init__(self, *, token: str | None = None, session: ClientSession | None = None) -> None:
45-
self.http: HTTPClient = HTTPClient(token=token, session=session)
43+
def __init__(self, *, session: ClientSession | None = None) -> None:
44+
self.http: HTTPClient = HTTPClient(session=session)
4645

4746
async def __aenter__(self) -> Self:
4847
return self
4948

5049
async def __aexit__(
51-
self,
52-
exc_cls: type[BaseException] | None,
53-
exc_value: BaseException | None,
54-
traceback: TracebackType | None
50+
self, exc_cls: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None
5551
) -> None:
5652
await self.close()
5753

@@ -62,52 +58,10 @@ async def close(self) -> None:
6258
"""
6359
await self.http.close()
6460

65-
@overload
66-
async def create_paste(
67-
self,
68-
*,
69-
filename: str,
70-
content: str,
71-
file: None = ...,
72-
files: None = ...,
73-
password: str | None = ...,
74-
expires: datetime.datetime | None = ...,
75-
) -> Paste:
76-
...
77-
78-
@overload
7961
async def create_paste(
8062
self,
8163
*,
82-
filename: None = ...,
83-
content: None = ...,
84-
file: File,
85-
files: None = ...,
86-
password: str | None = ...,
87-
expires: datetime.datetime | None = ...,
88-
) -> Paste:
89-
...
90-
91-
@overload
92-
async def create_paste(
93-
self,
94-
*,
95-
filename: None = ...,
96-
content: None = ...,
97-
file: None = ...,
9864
files: Sequence[File],
99-
password: str | None = ...,
100-
expires: datetime.datetime | None = ...,
101-
) -> Paste:
102-
...
103-
104-
async def create_paste(
105-
self,
106-
*,
107-
filename: str | None = None,
108-
content: str | None = None,
109-
file: File | None = None,
110-
files: Sequence[File] | None = None,
11165
password: str | None = None,
11266
expires: datetime.datetime | None = None,
11367
) -> Paste:
@@ -117,84 +71,41 @@ async def create_paste(
11771
11872
Parameters
11973
-----------
120-
filename: Optional[:class:`str`]
121-
The filename to create.
122-
content: Optional[:class:`str`]
123-
The content of the file you are creating.
124-
file: Optional[:class:`~mystbin.File`]
125-
The pre-created file you wish to upload.
126-
files: Optional[List[:class:`~mystbin.File`]]
74+
files: List[:class:`~mystbin.File`]
12775
The pre-creates list of files you wish to upload.
12876
password: Optional[:class:`str`]
12977
The password of the paste, if any.
13078
expires: Optional[:class:`datetime.datetime`]
13179
When the paste expires, if any.
13280
133-
Raises
134-
-------
135-
:exc:`ValueError`
136-
A bad combinarion of singular and plural pastes were passed.
137-
13881
Returns
13982
--------
14083
:class:`mystbin.Paste`
14184
The paste that was created.
142-
143-
144-
..note::
145-
Passing combinations of both singular and plural files is not supports and will raise an exception.
146-
Internally the order of precesence is ``files`` > ``file`` > ``filename and content``.
14785
"""
148-
if (filename and content) and file:
149-
raise ValueError("Cannot provide both `file` and `filename`/`content`")
150-
151-
resolved_files: Sequence[File] = []
152-
if filename and content:
153-
resolved_files = [File(filename=filename, content=content, attachment_url=None)]
154-
elif file:
155-
resolved_files = [file]
86+
data = await self.http.create_paste(files=files, password=password, expires=expires)
87+
return Paste.from_create(data, files=files)
15688

157-
if resolved_files and files:
158-
raise ValueError("Cannot provide both singular and plural files.")
159-
160-
resolved_files = files or resolved_files
161-
162-
data = await self.http.create_paste(files=resolved_files, password=password, expires=expires)
163-
return Paste.from_data(data)
164-
165-
@require_authentication
166-
async def delete_paste(self, paste_id: str, /) -> None:
89+
async def delete_paste(self, security_token: str, /) -> None:
16790
"""|coro|
16891
16992
Delete a paste.
17093
17194
Parameters
17295
-----------
173-
paste_id: :class:`str`
174-
The paste to delete.
96+
security_token: :class:`str`
97+
The security token relating to the paste to delete.
17598
"""
176-
await self.http.delete_pastes(paste_ids=[paste_id])
177-
178-
@require_authentication
179-
async def delete_pastes(self, paste_ids: list[str], /) -> None:
180-
"""|coro|
99+
await self.http.delete_paste(security_token)
181100

182-
Delete multiple pastes.
183-
184-
Parameters
185-
-----------
186-
paste_ids: List[:class:`str`]
187-
The pastes to delete.
188-
"""
189-
await self.http.delete_pastes(paste_ids=paste_ids)
101+
@overload
102+
async def get_paste(self, paste_id: str, *, password: str | None = ..., raw: Literal[False]) -> Paste: ...
190103

191104
@overload
192-
async def get_paste(self, paste_id: str, *, password: str | None = ..., raw: Literal[False]) -> Paste:
193-
...
105+
async def get_paste(self, paste_id: str, *, password: str | None = ..., raw: Literal[True]) -> list[str]: ...
194106

195107
@overload
196-
async def get_paste(self, paste_id: str, *, password: str | None = ..., raw: Literal[True]) -> list[str]:
197-
...
108+
async def get_paste(self, paste_id: str, *, password: str | None = ...) -> Paste: ...
198109

199110
async def get_paste(self, paste_id: str, *, password: str | None = None, raw: bool = False) -> Paste | list[str]:
200111
"""|coro|
@@ -219,24 +130,4 @@ async def get_paste(self, paste_id: str, *, password: str | None = None, raw: bo
219130
data = await self.http.get_paste(paste_id=paste_id, password=password)
220131
if raw:
221132
return [item["content"] for item in data["files"]]
222-
return Paste.from_data(data)
223-
224-
@require_authentication
225-
async def get_user_pastes(self, *, limit: int = 100) -> list[Paste]:
226-
"""|coro|
227-
228-
Get all pastes belonging to the current authenticated user.
229-
230-
Parameters
231-
-----------
232-
limit: :class:`int`
233-
The amount of pastes to fetch. Defaults to ``100``.
234-
235-
Returns
236-
--------
237-
List[:class:`Paste`]
238-
The pastes that were fetched.
239-
"""
240-
data = await self.http.get_my_pastes(limit=limit)
241-
242-
return [Paste.from_data(x) for x in data]
133+
return Paste.from_get(data)

mystbin/errors.py

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2020
DEALINGS IN THE SOFTWARE.
2121
"""
22+
2223
from aiohttp import ClientResponse
2324

2425
__all__ = (

mystbin/http.py

+16-53
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343

4444
from . import __version__
4545
from .errors import APIException
46-
from .utils import MISSING
4746

4847
if TYPE_CHECKING:
4948
from types import TracebackType
@@ -54,7 +53,8 @@
5453
Response = Coroutine[None, None, T]
5554
MU = TypeVar("MU", bound="MaybeUnlock")
5655
BE = TypeVar("BE", bound=BaseException)
57-
from .types.responses import EditPasteResponse, PasteResponse
56+
from .types.responses import CreatePasteResponse, GetPasteResponse
57+
5858

5959
SupportedHTTPVerb = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
6060

@@ -112,7 +112,7 @@ class Route:
112112
"url",
113113
)
114114

115-
API_BASE: ClassVar[str] = "https://api.mystb.in"
115+
API_BASE: ClassVar[str] = "https://mystb.in/api"
116116

117117
def __init__(self, verb: SupportedHTTPVerb, path: str, **params: Any) -> None:
118118
self.verb: SupportedHTTPVerb = verb
@@ -133,8 +133,7 @@ class HTTPClient:
133133
"user_agent",
134134
)
135135

136-
def __init__(self, *, token: str | None, session: aiohttp.ClientSession | None = None) -> None:
137-
self._token: str | None = token
136+
def __init__(self, *, session: aiohttp.ClientSession | None = None) -> None:
138137
self._session: aiohttp.ClientSession | None = session
139138
self._owns_session: bool = False
140139
self._locks: weakref.WeakValueDictionary[str, asyncio.Lock] = weakref.WeakValueDictionary()
@@ -161,9 +160,6 @@ async def request(self, route: Route, **kwargs: Any) -> Any:
161160
self._locks[bucket] = lock
162161

163162
headers = kwargs.pop("headers", {})
164-
165-
if self._token is not None:
166-
headers["Authorization"] = f"Bearer {self._token}"
167163
headers["User-Agent"] = self.user_agent
168164

169165
if "json" in kwargs:
@@ -222,6 +218,7 @@ async def request(self, route: Route, **kwargs: Any) -> Any:
222218
await asyncio.sleep(sleep_)
223219
continue
224220

221+
print(data)
225222
assert isinstance(data, dict)
226223
LOGGER.exception("Unhandled HTTP error occurred: %s -> %s", response.status, data)
227224
raise APIException(
@@ -244,64 +241,30 @@ async def request(self, route: Route, **kwargs: Any) -> Any:
244241
def create_paste(
245242
self,
246243
*,
247-
file: File | None = None,
248-
files: Sequence[File] | None = None,
244+
files: Sequence[File],
249245
password: str | None,
250246
expires: datetime.datetime | None,
251-
) -> Response[PasteResponse]:
252-
route = Route("PUT", "/paste")
247+
) -> Response[CreatePasteResponse]:
248+
route = Route("POST", "/paste")
253249

254250
json_: dict[str, Any] = {}
255-
if file:
256-
json_["files"] = [file.to_dict()]
257-
elif files:
258-
json_["files"] = [f.to_dict() for f in files]
251+
headers: dict[str, Any] = {}
252+
json_["files"] = [f.to_dict() for f in files]
259253

260254
if password:
261-
json_["password"] = password
255+
headers["password"] = password
262256
if expires:
263257
json_["expires"] = _clean_dt(expires)
264258

265-
return self.request(route=route, json=json_)
259+
return self.request(route=route, json=json_, headers=headers)
266260

267-
def delete_paste(self, *, paste_id: str) -> Response[None]:
268-
return self.delete_pastes(paste_ids=[paste_id])
261+
def delete_paste(self, security_token: str, /) -> Response[bool]:
262+
route = Route("GET", "/security/delete/{security_token}", security_token=security_token)
263+
return self.request(route)
269264

270-
def delete_pastes(self, *, paste_ids: Sequence[str]) -> Response[None]:
271-
route = Route("DELETE", "/paste")
272-
return self.request(route=route, json={"pastes": paste_ids})
273-
274-
def get_paste(self, *, paste_id: str, password: str | None) -> Response[PasteResponse]:
265+
def get_paste(self, *, paste_id: str, password: str | None) -> Response[GetPasteResponse]:
275266
route = Route("GET", "/paste/{paste_id}", paste_id=paste_id)
276267

277268
if password:
278269
return self.request(route=route, params={"password": password})
279270
return self.request(route=route)
280-
281-
def edit_paste(
282-
self,
283-
paste_id: str,
284-
*,
285-
new_content: str = MISSING,
286-
new_filename: str = MISSING,
287-
new_expires: datetime.datetime = MISSING,
288-
) -> Response[EditPasteResponse]:
289-
route = Route("PATCH", "/paste/{paste_id}", paste_id=paste_id)
290-
291-
json_: dict[str, Any] = {}
292-
293-
if new_content is not MISSING:
294-
json_["new_content"] = new_content
295-
296-
if new_filename is not MISSING:
297-
json_["new_filename"] = new_filename
298-
299-
if new_expires is not MISSING:
300-
json_["new_expires"] = _clean_dt(new_expires)
301-
302-
return self.request(route, json=json_)
303-
304-
def get_my_pastes(self, *, limit: int) -> Response[Sequence[PasteResponse]]:
305-
route = Route("GET", "/pastes/@me")
306-
307-
return self.request(route, params={limit: limit})

0 commit comments

Comments
 (0)