Skip to content

Commit 05953bb

Browse files
committed
Library typing is fixed, new version
1 parent 9877ee1 commit 05953bb

File tree

7 files changed

+309
-310
lines changed

7 files changed

+309
-310
lines changed

mystbin/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ class VersionInfo(NamedTuple):
3636
serial: int
3737

3838

39-
__version__ = "2.1.3"
40-
version_info: VersionInfo = VersionInfo(major=2, minor=1, micro=3, releaselevel="final", serial=0)
39+
__version__ = "2.2.0"
40+
version_info: VersionInfo = VersionInfo(major=2, minor=2, micro=0, releaselevel="final", serial=0)

mystbin/__main__.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2222
DEALINGS IN THE SOFTWARE.
2323
"""
24+
from __future__ import annotations
2425

2526
import argparse
2627
import platform
2728
import sys
29+
from typing import List, Tuple
2830

2931
import aiohttp
3032
import pkg_resources
@@ -38,39 +40,43 @@
3840
import mystbin
3941

4042

41-
def show_version():
42-
entries = []
43+
def show_version() -> None:
44+
entries: List[str] = []
4345

4446
entries.append("- Python v{0.major}.{0.minor}.{0.micro}-{0.releaselevel}".format(sys.version_info))
4547
version_info = mystbin.version_info
4648
entries.append("- mystbin.py v{0.major}.{0.minor}.{0.micro}-{0.releaselevel}".format(version_info))
49+
4750
if version_info.releaselevel != "final":
4851
pkg = pkg_resources.get_distribution("mystbin.py")
4952
if pkg:
5053
entries.append(" - mystbin.py pkg_resources: v{0}".format(pkg.version))
5154

5255
entries.append("- aiohttp v{0.__version__}".format(aiohttp))
56+
5357
if requests is not None:
5458
entries.append(" - [requests] v{0.__version__}".format(requests))
59+
5560
uname = platform.uname()
5661
entries.append("- system info: {0.system} {0.release} {0.version}".format(uname))
62+
5763
print("\n".join(entries))
5864

5965

60-
def parse_args():
66+
def parse_args() -> Tuple[argparse.ArgumentParser, argparse.Namespace]:
6167
parser = argparse.ArgumentParser(prog="mystbin", description="Tools for helping with mystbin.py")
6268
parser.add_argument("-v", "--version", action="store_true", help="shows the wrapper version")
6369
parser.set_defaults(func=core)
6470

6571
return parser, parser.parse_args()
6672

6773

68-
def core(parser, args):
74+
def core(_: argparse.ArgumentParser, args: argparse.Namespace) -> None:
6975
if args.version:
7076
show_version()
7177

7278

73-
def main():
79+
def main() -> None:
7480
parser, args = parse_args()
7581
args.func(parser, args)
7682

mystbin/client.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from __future__ import annotations
2525

2626
import json
27-
from typing import TYPE_CHECKING, Awaitable, Optional, Union
27+
from typing import TYPE_CHECKING, Coroutine, Optional, Union
2828

2929
import aiohttp
3030

@@ -45,41 +45,37 @@ class HTTPClient:
4545
4646
Attributes
4747
----------
48-
api_key: Optional[:class:`str`]
49-
Your private API token to access the Mystb.in API.
50-
Currently unobtainable.
5148
session: Optional[Union[:class:`aiohttp.ClientSession`, :class:`requests.Session`]]
5249
Optional session to be passed to the creation of the client.
5350
"""
5451

55-
__slots__ = ("api_key", "session", "_are_we_async")
52+
__slots__ = (
53+
"session",
54+
"_are_we_async",
55+
)
5656

5757
def __init__(
5858
self,
5959
*,
60-
api_key: str = "",
6160
session: Optional[Union[aiohttp.ClientSession, requests.Session]] = None,
6261
) -> None:
63-
self.api_key = api_key
6462
self._are_we_async = session is None or isinstance(session, aiohttp.ClientSession)
65-
self.session = session
63+
self.session = session # type: ignore
6664

67-
async def _generate_async_session(self) -> aiohttp.ClientSession:
65+
async def _generate_async_session(self) -> None:
6866
"""
6967
This method will create a new and blank `aiohttp.ClientSession` instance for use.
7068
This method should not be called if a session is passed to the constructor.
7169
"""
72-
self.session = aiohttp.ClientSession()
70+
self.session: aiohttp.ClientSession = aiohttp.ClientSession()
7371

74-
return self.session
75-
76-
def post(self, content: str, syntax: str = None) -> Union[Paste, Awaitable]:
72+
def post(self, content: str, syntax: str = None) -> Union[Paste, Coroutine[None, None, Paste]]:
7773
"""
7874
This will post to the Mystb.in API and return the url.
7975
Can pass an optional suffix for the syntax highlighting.
8076
8177
Parameters
82-
----------
78+
-----------
8379
content: :class:`str`
8480
The content you are posting to the Mystb.in API.
8581
syntax: :class:`str`
@@ -90,16 +86,19 @@ def post(self, content: str, syntax: str = None) -> Union[Paste, Awaitable]:
9086
return self._perform_sync_post(content, syntax)
9187

9288
def _perform_sync_post(self, content: str, syntax: str = None) -> Paste:
93-
""" Sync post request. """
89+
assert not isinstance(self.session, aiohttp.ClientSession)
90+
9491
payload = {"meta": [{"index": 0, "syntax": syntax}]}
92+
93+
assert self.session is not None and not isinstance(self.session, aiohttp.ClientSession)
94+
9595
response: requests.Response = self.session.post(
9696
API_BASE_URL,
9797
files={
9898
"data": content,
9999
"meta": (None, json.dumps(payload), "application/json"),
100100
},
101101
timeout=CLIENT_TIMEOUT,
102-
headers={"Authorization": self.api_key},
103102
)
104103

105104
if response.status_code not in [200, 201]:
@@ -108,9 +107,10 @@ def _perform_sync_post(self, content: str, syntax: str = None) -> Paste:
108107
return Paste(response.json(), syntax)
109108

110109
async def _perform_async_post(self, content: str, syntax: str = None) -> Paste:
111-
""" Async post request. """
112110
if not self.session and self._are_we_async:
113-
self.session = await self._generate_async_session()
111+
await self._generate_async_session()
112+
113+
assert self.session is not None and isinstance(self.session, aiohttp.ClientSession)
114114

115115
multi_part_write = aiohttp.MultipartWriter()
116116
paste_content = multi_part_write.append(content)
@@ -122,17 +122,18 @@ async def _perform_async_post(self, content: str, syntax: str = None) -> Paste:
122122
API_BASE_URL,
123123
data=multi_part_write,
124124
timeout=aiohttp.ClientTimeout(CLIENT_TIMEOUT),
125-
headers={"Authorization": self.api_key},
126125
) as response:
127126
status_code = response.status
128127
response_text = await response.text()
129-
if status_code not in (200,):
128+
129+
if status_code != 200:
130130
raise APIError(status_code, response_text)
131+
131132
response_data = await response.json()
132133

133134
return Paste(response_data, syntax)
134135

135-
def get(self, paste_id: str) -> Union[PasteData, Awaitable]:
136+
def get(self, paste_id: str) -> Union[PasteData, Coroutine[None, None, PasteData]]:
136137
"""
137138
This will perform a GET request against the Mystb.in API and return the url.
138139
Must be passed a valid paste ID or URL.
@@ -155,19 +156,20 @@ def get(self, paste_id: str) -> Union[PasteData, Awaitable]:
155156
return self._perform_async_get(paste_id)
156157

157158
def _perform_sync_get(self, paste_id: str) -> PasteData:
158-
""" Sync get request. """
159-
response: requests.Response = self.session.get(f"{API_BASE_URL}/{paste_id}", timeout=CLIENT_TIMEOUT)
159+
assert self.session is not None and not isinstance(self.session, aiohttp.ClientSession)
160160

161-
if response.status_code not in (200,):
162-
raise BadPasteID("This is an invalid Mystb.in paste ID.")
161+
with self.session.get(f"{API_BASE_URL}/{paste_id}", timeout=CLIENT_TIMEOUT) as response:
162+
if response.status_code not in (200,):
163+
raise BadPasteID("This is an invalid Mystb.in paste ID.")
163164

164165
paste_data = response.json()
165166
return PasteData(paste_id, paste_data)
166167

167168
async def _perform_async_get(self, paste_id: str) -> PasteData:
168-
""" Async get request. """
169169
if not self.session:
170-
self.session: aiohttp.ClientSession = await self._generate_async_session()
170+
await self._generate_async_session()
171+
172+
assert self.session is not None and isinstance(self.session, aiohttp.ClientSession)
171173

172174
async with self.session.get(f"{API_BASE_URL}/{paste_id}", timeout=aiohttp.ClientTimeout(CLIENT_TIMEOUT)) as response:
173175
if response.status not in (200,):
@@ -176,7 +178,7 @@ async def _perform_async_get(self, paste_id: str) -> PasteData:
176178

177179
return PasteData(paste_id, paste_data)
178180

179-
async def close(self):
180-
""" Async only - close the session. """
181+
async def close(self) -> None:
182+
"""Async only - close the session."""
181183
if self.session and isinstance(self.session, aiohttp.ClientSession):
182184
await self.session.close()

mystbin/errors.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626

2727

2828
class BadPasteID(ValueError):
29-
""" Bad Paste ID. """
29+
"""Bad Paste ID."""
3030

3131

3232
class MystbinException(Exception):
33-
""" Error when interacting with Mystbin. """
33+
"""Error when interacting with Mystbin."""
3434

3535

3636
class APIError(MystbinException):
@@ -48,8 +48,8 @@ class APIError(MystbinException):
4848
__slots__ = ("status_code", "message")
4949

5050
def __init__(self, status_code: int, message: str):
51-
self.status_code = status_code
52-
self.message = message
51+
self.status_code: int = status_code
52+
self.message: str = message
5353

5454
def __repr__(self) -> str:
5555
return f"<MystbinError status_code={self.status_code} message={self.message}>"

mystbin/objects.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import datetime
2626
from textwrap import dedent
27+
from typing import Any, Dict, Optional
2728

2829
from .constants import PASTE_BASE
2930

@@ -45,9 +46,9 @@ class Paste:
4546
__slots__ = ("paste_id", "nick", "syntax")
4647

4748
def __init__(self, json_data: dict, syntax: str = None):
48-
self.paste_id = json_data["pastes"][0]["id"]
49-
self.nick = json_data["pastes"][0]["nick"]
50-
self.syntax = syntax
49+
self.paste_id: str = json_data["pastes"][0]["id"]
50+
self.nick: Optional[str] = json_data["pastes"][0]["nick"]
51+
self.syntax: Optional[str] = syntax
5152

5253
def __str__(self) -> str:
5354
return self.url
@@ -61,7 +62,7 @@ def url(self) -> str:
6162
syntax = f".{self.syntax}" if self.syntax else ""
6263
return PASTE_BASE.format(self.paste_id, syntax)
6364

64-
def with_syntax(self, new_syntax: str) -> str:
65+
def with_syntax(self, new_syntax: Optional[str]) -> str:
6566
"""
6667
Changes the syntax of the current Paste to `new_syntax`
6768
@@ -86,9 +87,9 @@ class PasteData:
8687
The content returned from the paste.
8788
paste_syntax: :class:`str`
8889
The syntax you specified that this Paste is in.
89-
paste_nick: :class:`str`
90+
paste_nick: Optional[:class:`str`]
9091
The nick set for this paste on the API.
91-
paste_date: :class:`datetime.datetime`
92+
paste_date: :class:`str`
9293
The date this paste was created on the API.
9394
"""
9495

@@ -101,13 +102,13 @@ class PasteData:
101102
"paste_date",
102103
)
103104

104-
def __init__(self, paste_id: str, paste_data: dict):
105-
self.paste_id = paste_id
106-
self._paste_data = paste_data
107-
self.paste_content = paste_data["data"]
108-
self.paste_syntax = paste_data["syntax"]
109-
self.paste_nick = paste_data["nick"]
110-
self.paste_date = paste_data["created_at"]
105+
def __init__(self, paste_id: str, paste_data: Dict[str, Any]):
106+
self.paste_id: str = paste_id
107+
self._paste_data: Dict[str, Any] = paste_data
108+
self.paste_content: str = paste_data["data"]
109+
self.paste_syntax: str = paste_data["syntax"]
110+
self.paste_nick: Optional[str] = paste_data["nick"]
111+
self.paste_date: str = paste_data["created_at"]
111112

112113
def __str__(self) -> str:
113114
return self.content

0 commit comments

Comments
 (0)