Apply several lints

This commit is contained in:
Lonami Exo 2019-05-03 13:59:17 +02:00
parent 52be689926
commit 1e17ef1c98
22 changed files with 78 additions and 53 deletions

View File

@ -9,7 +9,7 @@ If you have a question, ask in https://stackoverflow.com or find the link for th
If you paste code, please put it between three backticks (`): If you paste code, please put it between three backticks (`):
```python ```python
code here # python code here
``` ```
Once you have read and understood this, delete all this text and detail whatever issue you are posting. Once you have read and understood this, delete all this text and detail whatever issue you are posting.

View File

@ -28,6 +28,7 @@ def make_link_node(rawtext, app, name, options):
return node return node
# noinspection PyUnusedLocal
def tl_role(name, rawtext, text, lineno, inliner, options=None, content=None): def tl_role(name, rawtext, text, lineno, inliner, options=None, content=None):
""" """
Link to the TL reference. Link to the TL reference.
@ -45,8 +46,6 @@ def tl_role(name, rawtext, text, lineno, inliner, options=None, content=None):
""" """
if options is None: if options is None:
options = {} options = {}
if content is None:
content = []
# TODO Report error on type not found? # TODO Report error on type not found?
# Usage: # Usage:

View File

@ -119,19 +119,19 @@ def generate(which):
file.unlink() file.unlink()
else: else:
def gen_json(fin, fout): def gen_json(fin, fout):
methods = [] meths = []
constructors = [] constructors = []
for tl in parse_tl(fin, layer): for tl in parse_tl(fin, layer):
if tl.is_function: if tl.is_function:
methods.append(tl.to_dict()) meths.append(tl.to_dict())
else: else:
constructors.append(tl.to_dict()) constructors.append(tl.to_dict())
what = {'constructors': constructors, 'methods': methods} what = {'constructors': constructors, 'methods': meths}
with open(fout, 'w') as f: with open(fout, 'w') as f:
json.dump(what, f, indent=2) json.dump(what, f, indent=2)
for fin, fout in zip(TLOBJECT_IN_TLS, json_files): for fs in zip(TLOBJECT_IN_TLS, json_files):
gen_json(fin, fout) gen_json(*fs)
if which: if which:
print('The following items were not understood:', which) print('The following items were not understood:', which)

View File

@ -4,7 +4,8 @@ from .. import utils, events
class ButtonMethods(UpdateMethods): class ButtonMethods(UpdateMethods):
def build_reply_markup(self, buttons, inline_only=False): @staticmethod
def build_reply_markup(buttons, inline_only=False):
""" """
Builds a :tl`ReplyInlineMarkup` or :tl:`ReplyKeyboardMarkup` for Builds a :tl`ReplyInlineMarkup` or :tl:`ReplyKeyboardMarkup` for
the given buttons, or does nothing if either no buttons are the given buttons, or does nothing if either no buttons are

View File

@ -57,6 +57,8 @@ class DownloadMethods(UserMethods):
if not isinstance(entity, TLObject) or entity.SUBCLASS_OF_ID in INPUTS: if not isinstance(entity, TLObject) or entity.SUBCLASS_OF_ID in INPUTS:
entity = await self.get_entity(entity) entity = await self.get_entity(entity)
thumb = -1 if download_big else 0
possible_names = [] possible_names = []
if entity.SUBCLASS_OF_ID not in ENTITIES: if entity.SUBCLASS_OF_ID not in ENTITIES:
photo = entity photo = entity
@ -68,7 +70,9 @@ class DownloadMethods(UserMethods):
return None return None
return await self._download_photo( return await self._download_photo(
entity.chat_photo, file, date=None, progress_callback=None) entity.chat_photo, file, date=None,
thumb=thumb, progress_callback=None
)
for attr in ('username', 'first_name', 'title'): for attr in ('username', 'first_name', 'title'):
possible_names.append(getattr(entity, attr, None)) possible_names.append(getattr(entity, attr, None))
@ -108,7 +112,7 @@ class DownloadMethods(UserMethods):
return await self._download_photo( return await self._download_photo(
full.full_chat.chat_photo, file, full.full_chat.chat_photo, file,
date=None, progress_callback=None, date=None, progress_callback=None,
thumb=-1 if download_big else 0 thumb=thumb
) )
else: else:
# Until there's a report for chats, no need to. # Until there's a report for chats, no need to.
@ -333,7 +337,8 @@ class DownloadMethods(UserMethods):
else: else:
return None return None
def _download_cached_photo_size(self, size, file): @staticmethod
def _download_cached_photo_size(size, file):
# No need to download anything, simply write the bytes # No need to download anything, simply write the bytes
if file is bytes: if file is bytes:
return size.bytes return size.bytes

View File

@ -1,5 +0,0 @@
"""
Sentinel module to signify that a parameter should use its default value.
Useful when the default value or ``None`` are both valid options.
"""

View File

@ -26,13 +26,13 @@ def rpc_message_to_error(rpc_error, request):
# Try to get the error by direct look-up, otherwise regex # Try to get the error by direct look-up, otherwise regex
cls = rpc_errors_dict.get(rpc_error.error_message, None) cls = rpc_errors_dict.get(rpc_error.error_message, None)
if cls: if cls:
return cls(request) return cls(request=request)
for msg_regex, cls in rpc_errors_re: for msg_regex, cls in rpc_errors_re:
m = re.match(msg_regex, rpc_error.error_message) m = re.match(msg_regex, rpc_error.error_message)
if m: if m:
capture = int(m.group(1)) if m.groups() else None capture = int(m.group(1)) if m.groups() else None
return cls(request, capture=capture) return cls(request=request, capture=capture)
# Some errors are negative: # Some errors are negative:
# * -500 for "No workers running", # * -500 for "No workers running",
@ -40,8 +40,6 @@ def rpc_message_to_error(rpc_error, request):
# #
# We treat them as if they were positive, so -500 will be treated # We treat them as if they were positive, so -500 will be treated
# as a `ServerError`, etc. # as a `ServerError`, etc.
cls = base_errors.get(abs(rpc_error.error_code)) cls = base_errors.get(abs(rpc_error.error_code), RPCError)
if cls: return cls(request=request, message=rpc_error.error_message,
return cls(request, rpc_error.error_message) code=rpc_error.error_code)
return RPCError(request, rpc_error.error_message, rpc_error.error_code)

View File

@ -248,7 +248,7 @@ class PacketCodec(abc.ABC):
""" """
Codec is created when connection is just made. Codec is created when connection is just made.
""" """
pass self._conn = connection
@abc.abstractmethod @abc.abstractmethod
def encode_packet(self, data): def encode_packet(self, data):

View File

@ -10,10 +10,6 @@ class HttpPacketCodec(PacketCodec):
tag = None tag = None
obfuscate_tag = None obfuscate_tag = None
def __init__(self, connection):
self._ip = connection._ip
self._port = connection._port
def encode_packet(self, data): def encode_packet(self, data):
return ('POST /api HTTP/1.1\r\n' return ('POST /api HTTP/1.1\r\n'
'Host: {}:{}\r\n' 'Host: {}:{}\r\n'
@ -21,7 +17,7 @@ class HttpPacketCodec(PacketCodec):
'Connection: keep-alive\r\n' 'Connection: keep-alive\r\n'
'Keep-Alive: timeout=100000, max=10000000\r\n' 'Keep-Alive: timeout=100000, max=10000000\r\n'
'Content-Length: {}\r\n\r\n' 'Content-Length: {}\r\n\r\n'
.format(self._ip, self._port, len(data)) .format(self._conn._ip, self._conn._port, len(data))
.encode('ascii') + data) .encode('ascii') + data)
async def read_packet(self, reader): async def read_packet(self, reader):

View File

@ -8,7 +8,8 @@ from ...errors import InvalidChecksumError
class FullPacketCodec(PacketCodec): class FullPacketCodec(PacketCodec):
tag = None tag = None
def __init__(self, _conn): def __init__(self, connection):
super().__init__(connection)
self._send_counter = 0 # Important or Telegram won't reply self._send_counter = 0 # Important or Telegram won't reply
def encode_packet(self, data): def encode_packet(self, data):

View File

@ -28,7 +28,8 @@ class MTProxyIO:
self._decrypt) = self.init_header( self._decrypt) = self.init_header(
connection._secret, connection._dc_id, connection.packet_codec) connection._secret, connection._dc_id, connection.packet_codec)
def init_header(self, secret, dc_id, packet_codec): @staticmethod
def init_header(secret, dc_id, packet_codec):
# Validate # Validate
is_dd = (len(secret) == 17) and (secret[0] == 0xDD) is_dd = (len(secret) == 17) and (secret[0] == 0xDD)
is_rand_codec = issubclass( is_rand_codec = issubclass(
@ -93,6 +94,14 @@ class TcpMTProxy(ObfuscatedConnection):
packet_codec = None packet_codec = None
obfuscated_io = MTProxyIO obfuscated_io = MTProxyIO
# noinspection PyUnusedLocal
def __init__(self, ip, port, dc_id, *, loop, loggers, proxy=None):
# connect to proxy's host and port instead of telegram's ones
proxy_host, proxy_port = self.address_info(proxy)
self._secret = bytes.fromhex(proxy[2])
super().__init__(
proxy_host, proxy_port, dc_id, loop=loop, loggers=loggers)
async def _connect(self, timeout=None, ssl=None): async def _connect(self, timeout=None, ssl=None):
await super()._connect(timeout=timeout, ssl=ssl) await super()._connect(timeout=timeout, ssl=ssl)
@ -121,13 +130,6 @@ class TcpMTProxy(ObfuscatedConnection):
raise ValueError("No proxy info specified for MTProxy connection") raise ValueError("No proxy info specified for MTProxy connection")
return proxy_info[:2] return proxy_info[:2]
def __init__(self, ip, port, dc_id, *, loop, loggers, proxy=None):
# connect to proxy's host and port instead of telegram's ones
proxy_host, proxy_port = self.address_info(proxy)
self._secret = bytes.fromhex(proxy[2])
super().__init__(
proxy_host, proxy_port, dc_id, loop=loop, loggers=loggers)
class ConnectionTcpMTProxyAbridged(TcpMTProxy): class ConnectionTcpMTProxyAbridged(TcpMTProxy):
""" """

View File

@ -17,7 +17,8 @@ class ObfuscatedIO:
self._encrypt, self._encrypt,
self._decrypt) = self.init_header(connection.packet_codec) self._decrypt) = self.init_header(connection.packet_codec)
def init_header(self, packet_codec): @staticmethod
def init_header(packet_codec):
# Obfuscated messages secrets cannot start with any of these # Obfuscated messages secrets cannot start with any of these
keywords = (b'PVrG', b'GET ', b'POST', b'\xee\xee\xee\xee') keywords = (b'PVrG', b'GET ', b'POST', b'\xee\xee\xee\xee')
while True: while True:

View File

@ -39,6 +39,8 @@ class MTProtoState:
self._log = loggers[__name__] self._log = loggers[__name__]
self.time_offset = 0 self.time_offset = 0
self.salt = 0 self.salt = 0
self.id = self._sequence = self._last_msg_id = None
self.reset() self.reset()
def reset(self): def reset(self):

View File

@ -86,7 +86,8 @@ class MemorySession(Session):
def delete(self): def delete(self):
pass pass
def _entity_values_to_row(self, id, hash, username, phone, name): @staticmethod
def _entity_values_to_row(id, hash, username, phone, name):
# While this is a simple implementation it might be overrode by, # While this is a simple implementation it might be overrode by,
# other classes so they don't need to implement the plural form # other classes so they don't need to implement the plural form
# of the method. Don't remove. # of the method. Don't remove.

View File

@ -25,10 +25,7 @@ class StringSession(MemorySession):
* `encode` definition must be ``def encode(value: bytes) -> str:``. * `encode` definition must be ``def encode(value: bytes) -> str:``.
* `decode` definition must be ``def decode(value: str) -> bytes:``. * `decode` definition must be ``def decode(value: str) -> bytes:``.
""" """
encode = lambda x: base64.urlsafe_b64encode(x).decode('ascii') def __init__(self, string: str = None):
decode = base64.urlsafe_b64decode
def __init__(self, string=None):
super().__init__() super().__init__()
if string: if string:
if string[0] != CURRENT_VERSION: if string[0] != CURRENT_VERSION:
@ -37,18 +34,26 @@ class StringSession(MemorySession):
string = string[1:] string = string[1:]
ip_len = 4 if len(string) == 352 else 16 ip_len = 4 if len(string) == 352 else 16
self._dc_id, ip, self._port, key = struct.unpack( self._dc_id, ip, self._port, key = struct.unpack(
_STRUCT_PREFORMAT.format(ip_len), StringSession.decode(string)) _STRUCT_PREFORMAT.format(ip_len), self.decode(string))
self._server_address = ipaddress.ip_address(ip).compressed self._server_address = ipaddress.ip_address(ip).compressed
if any(key): if any(key):
self._auth_key = AuthKey(key) self._auth_key = AuthKey(key)
@staticmethod
def encode(x: bytes) -> str:
return base64.urlsafe_b64encode(x).decode('ascii')
@staticmethod
def decode(x: str) -> bytes:
return base64.urlsafe_b64decode(x)
def save(self): def save(self):
if not self._auth_key: if not self._auth_key:
return '' return ''
ip = ipaddress.ip_address(self._server_address).packed ip = ipaddress.ip_address(self._server_address).packed
return CURRENT_VERSION + StringSession.encode(struct.pack( return CURRENT_VERSION + self.encode(struct.pack(
_STRUCT_PREFORMAT.format(len(ip)), _STRUCT_PREFORMAT.format(len(ip)),
self._dc_id, self._dc_id,
ip, ip,

View File

@ -14,6 +14,10 @@ class ChatGetter(abc.ABC):
`_input_chat`, `_chat_peer`, `_broadcast` and `_client`. As an end `_input_chat`, `_chat_peer`, `_broadcast` and `_client`. As an end
user, you should not worry about this. user, you should not worry about this.
""" """
def __init__(self):
self._chat = self._input_chat = self._chat_peer = \
self._client = self._broadcast = None
@property @property
def chat(self): def chat(self):
""" """

View File

@ -56,6 +56,7 @@ class InlineBuilder:
def __init__(self, client): def __init__(self, client):
self._client = client self._client = client
# noinspection PyIncorrectDocstring
async def article( async def article(
self, title, description=None, self, title, description=None,
*, url=None, thumb=None, content=None, *, url=None, thumb=None, content=None,
@ -107,6 +108,7 @@ class InlineBuilder:
return result return result
# noinspection PyIncorrectDocstring
async def photo( async def photo(
self, file, *, id=None, self, file, *, id=None,
text=None, parse_mode=(), link_preview=True, text=None, parse_mode=(), link_preview=True,
@ -154,6 +156,7 @@ class InlineBuilder:
return result return result
# noinspection PyIncorrectDocstring
async def document( async def document(
self, file, title=None, *, description=None, type=None, self, file, title=None, *, description=None, type=None,
mime_type=None, attributes=None, force_document=False, mime_type=None, attributes=None, force_document=False,
@ -236,6 +239,7 @@ class InlineBuilder:
return result return result
# noinspection PyIncorrectDocstring
async def game( async def game(
self, short_name, *, id=None, self, short_name, *, id=None,
text=None, parse_mode=(), link_preview=True, text=None, parse_mode=(), link_preview=True,

View File

@ -519,12 +519,12 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC):
@property @property
def action_entities(self): def action_entities(self):
""" """
Returns a list of entities that can took part in this action. Returns a list of entities that took part in this action.
Possible cases for this are :tl:`MessageActionChatAddUser`, Possible cases for this are :tl:`MessageActionChatAddUser`,
:tl:`types.MessageActionChatCreate`, :tl:`MessageActionChatDeleteUser`, :tl:`types.MessageActionChatCreate`, :tl:`MessageActionChatDeleteUser`,
:tl:`MessageActionChatJoinedByLink` :tl:`MessageActionChatMigrateTo` :tl:`MessageActionChatJoinedByLink` :tl:`MessageActionChatMigrateTo`
and :tl:`MessageActionChannelMigrateFrom). and :tl:`MessageActionChannelMigrateFrom`.
If the action is neither of those, the result will be ``None``. If the action is neither of those, the result will be ``None``.
If some entities could not be retrieved, the list may contain If some entities could not be retrieved, the list may contain

View File

@ -11,6 +11,10 @@ class SenderGetter(abc.ABC):
`_input_sender`, `_sender_id` and `_client`. As an end user, you `_input_sender`, `_sender_id` and `_client`. As an end user, you
should not worry about this. should not worry about this.
""" """
def __init__(self):
self._sender = self._input_sender = self._sender_id = \
self._client = None
@property @property
def sender(self): def sender(self):
""" """
@ -79,3 +83,9 @@ class SenderGetter(abc.ABC):
""" """
Re-fetches sender information through other means. Re-fetches sender information through other means.
""" """
@abc.abstractmethod
async def _reload_message(self):
"""
Subclasses should implement message reloading.
"""

View File

@ -1139,8 +1139,6 @@ class AsyncClassWrapper:
if callable(w): if callable(w):
return wrapper return wrapper
elif isinstance(w, property):
return w.fget(self.wrapped)
else: else:
return w return w

View File

@ -27,7 +27,7 @@ def generate_errors(errors, f):
# Error classes generation # Error classes generation
for error in errors: for error in errors:
f.write('\n\nclass {}({}):\n' f.write('\n\nclass {}({}):\n'
' def __init__(self, request, **kwargs):\n' ' def __init__(self, **kwargs):\n'
' '.format(error.name, error.subclass)) ' '.format(error.name, error.subclass))
if error.has_captures: if error.has_captures:
@ -40,7 +40,7 @@ def generate_errors(errors, f):
if error.has_captures: if error.has_captures:
f.write('.format({0}=self.{0})'.format(error.capture_name)) f.write('.format({0}=self.{0})'.format(error.capture_name))
f.write(' + self._fmt_request(request))\n') f.write(" + self._fmt_request(kwargs['request']))\n")
# Create the actual {CODE: ErrorClassName} dict once classes are defined # Create the actual {CODE: ErrorClassName} dict once classes are defined
f.write('\n\nrpc_errors_dict = {\n') f.write('\n\nrpc_errors_dict = {\n')

View File

@ -206,6 +206,9 @@ def _write_class_init(tlobject, kind, type_constructors, builder):
if not tlobject.real_args: if not tlobject.real_args:
return return
if any(a.name in __builtins__ for a in tlobject.real_args):
builder.writeln('# noinspection PyShadowingBuiltins')
builder.writeln("def __init__({}):", ', '.join(['self'] + args)) builder.writeln("def __init__({}):", ', '.join(['self'] + args))
builder.writeln('"""') builder.writeln('"""')
if tlobject.is_function: if tlobject.is_function: