Address more pylint and py3 compatibility problems

This commit is contained in:
Ammar Askar 2015-04-03 02:25:34 +05:00
parent dcb2845ac4
commit c353d8bb86
6 changed files with 63 additions and 55 deletions

View File

@ -4,10 +4,9 @@ Handles authentication with the Mojang authentication server.
import requests import requests
import json import json
from .exceptions import YggdrasilError from .exceptions import YggdrasilError
import collections
AUTHSERVER = "https://authserver.mojang.com" AUTH_SERVER = "https://authserver.mojang.com"
SESSIONSERVER = "https://sessionserver.mojang.com/session/minecraft" SESSION_SERVER = "https://sessionserver.mojang.com/session/minecraft"
# Need this content type, or authserver will complain # Need this content type, or authserver will complain
CONTENT_TYPE = "application/json" CONTENT_TYPE = "application/json"
HEADERS = {"content-type": CONTENT_TYPE} HEADERS = {"content-type": CONTENT_TYPE}
@ -113,7 +112,7 @@ class AuthenticationToken(object):
"password": password "password": password
} }
req = _make_request(AUTHSERVER, "authenticate", payload) req = _make_request(AUTH_SERVER, "authenticate", payload)
_raise_from_request(req) _raise_from_request(req)
@ -148,7 +147,7 @@ class AuthenticationToken(object):
if self.client_token is None: if self.client_token is None:
raise ValueError("'client_token' is not set!") raise ValueError("'client_token' is not set!")
req = _make_request(AUTHSERVER, req = _make_request(AUTH_SERVER,
"refresh", {"accessToken": self.access_token, "refresh", {"accessToken": self.access_token,
"clientToken": self.client_token}) "clientToken": self.client_token})
@ -180,7 +179,7 @@ class AuthenticationToken(object):
if self.access_token is None: if self.access_token is None:
raise ValueError("'access_token' not set!") raise ValueError("'access_token' not set!")
req = _make_request(AUTHSERVER, "validate", req = _make_request(AUTH_SERVER, "validate",
{"accessToken": self.access_token}) {"accessToken": self.access_token})
if _raise_from_request(req) is None: if _raise_from_request(req) is None:
@ -203,8 +202,8 @@ class AuthenticationToken(object):
Raises: Raises:
minecraft.exceptions.YggdrasilError minecraft.exceptions.YggdrasilError
""" """
req = _make_request(AUTHSERVER, "signout", {"username": username, req = _make_request(AUTH_SERVER, "signout",
"password": password}) {"username": username, "password": password})
if _raise_from_request(req) is None: if _raise_from_request(req) is None:
return True return True
@ -220,11 +219,11 @@ class AuthenticationToken(object):
Raises: Raises:
:class:`minecraft.exceptions.YggdrasilError` :class:`minecraft.exceptions.YggdrasilError`
""" """
req = _make_request(AUTHSERVER, "invalidate", req = _make_request(AUTH_SERVER, "invalidate",
{"accessToken": self.access_token, {"accessToken": self.access_token,
"clientToken": self.client_token}) "clientToken": self.client_token})
if status_code == requests.codes.ok and not req.text: if not req.raise_for_status() and not req.text:
return True return True
else: else:
raise YggdrasilError("Failed to invalidate tokens.") raise YggdrasilError("Failed to invalidate tokens.")
@ -248,7 +247,7 @@ class AuthenticationToken(object):
err = "AuthenticationToken hasn't been authenticated yet!" err = "AuthenticationToken hasn't been authenticated yet!"
raise YggdrasilError(err) raise YggdrasilError(err)
req = _make_request(SESSIONSERVER, "join", req = _make_request(SESSION_SERVER, "join",
{"accessToken": self.access_token, {"accessToken": self.access_token,
"selectedProfile": self.profile.to_dict(), "selectedProfile": self.profile.to_dict(),
"serverId": server_id}) "serverId": server_id})

View File

@ -9,7 +9,7 @@ import select
import packets import packets
from types import VarInt from types import VarInt
from minecraft import PROTOCOL_VERSION from .. import PROTOCOL_VERSION
class ConnectionOptions(object): class ConnectionOptions(object):
@ -173,7 +173,7 @@ class NetworkingThread(threading.Thread):
break break
self.connection._write_lock.release() self.connection._write_lock.release()
# Read and react to as many as 50 packets # Read and react to as many as 50 packets
num_packets = 0 num_packets = 0
packet = self.connection.reactor.read_packet( packet = self.connection.reactor.read_packet(
self.connection.file_object) self.connection.file_object)
@ -205,8 +205,8 @@ class PacketReactor(object):
self.connection = connection self.connection = connection
def read_packet(self, stream): def read_packet(self, stream):
ready_to_read, _, __ = select.select([self.connection.socket], [], [], ready_to_read = select.select([self.connection.socket], [], [],
self.TIME_OUT) self.TIME_OUT)[0]
if self.connection.socket in ready_to_read: if self.connection.socket in ready_to_read:
length = VarInt.read_socket(self.connection.socket) length = VarInt.read_socket(self.connection.socket)
@ -278,8 +278,9 @@ class LoginReactor(PacketReactor):
decryptor = cipher.decryptor() decryptor = cipher.decryptor()
self.connection.socket = encryption.EncryptedSocketWrapper( self.connection.socket = encryption.EncryptedSocketWrapper(
self.connection.socket, encryptor, decryptor) self.connection.socket, encryptor, decryptor)
self.connection.file_object = encryption.EncryptedFileObjectWrapper( self.connection.file_object = \
self.connection.file_object, decryptor) encryption.EncryptedFileObjectWrapper(
self.connection.file_object, decryptor)
if packet.packet_name == "disconnect": if packet.packet_name == "disconnect":
print(packet.json_data) # TODO: handle propagating this back print(packet.json_data) # TODO: handle propagating this back
@ -328,7 +329,7 @@ class StatusReactor(PacketReactor):
if packet.id == packets.ResponsePacket.id: if packet.id == packets.ResponsePacket.id:
import json import json
print json.loads(packet.json_response) print(json.loads(packet.json_response))
ping_packet = packets.PingPacket() ping_packet = packets.PingPacket()
ping_packet.time = int(time.time()) ping_packet.time = int(time.time())

View File

@ -54,6 +54,11 @@ def minecraft_sha1_hash_digest(sha1_hash):
def _number_from_bytes(b, signed=False): def _number_from_bytes(b, signed=False):
try:
return int.from_bytes(b, byteorder='big', signed=signed)
except AttributeError:
pass
if len(b) == 0: if len(b) == 0:
b = b'\x00' b = b'\x00'
num = int(str(b).encode('hex'), 16) num = int(str(b).encode('hex'), 16)

View File

@ -1,36 +1,37 @@
from io import BytesIO from io import BytesIO
from zlib import compress from zlib import compress
from types import * from .types import (
VarInt, Integer, Float, Double, UnsignedShort, Long, Byte, UnsignedByte,
String, VarIntPrefixedByteArray, Boolean
)
class PacketBuffer(object): class PacketBuffer(object):
def __init__(self): def __init__(self):
self.b = BytesIO() self.bytes = BytesIO()
def send(self, value): def send(self, value):
""" """
Writes the given bytes to the buffer, designed to emulate socket.send Writes the given bytes to the buffer, designed to emulate socket.send
:param value: The bytes to write :param value: The bytes to write
""" """
self.b.write(value) self.bytes.write(value)
def read(self, length): def read(self, length):
return self.b.read(length) return self.bytes.read(length)
def reset(self): def reset(self):
self.b = BytesIO() self.bytes = BytesIO()
def reset_cursor(self): def reset_cursor(self):
self.b.seek(0) self.bytes.seek(0)
def get_writable(self): def get_writable(self):
return self.b.getvalue() return self.bytes.getvalue()
class PacketListener(object): class PacketListener(object):
packets_to_listen = [] packets_to_listen = []
def __init__(self, callback, *args): def __init__(self, callback, *args):
@ -46,7 +47,6 @@ class PacketListener(object):
class Packet(object): class Packet(object):
packet_name = "base" packet_name = "base"
id = -0x01 id = -0x01
definition = [] definition = []
@ -61,7 +61,8 @@ class Packet(object):
setattr(self, var_name, value) setattr(self, var_name, value)
def write(self, socket, compression_threshold=None): def write(self, socket, compression_threshold=None):
# buffer the data since we need to know the length of each packet's payload # buffer the data since we need to know the length of each packet's
# payload
packet_buffer = PacketBuffer() packet_buffer = PacketBuffer()
# write packet's id right off the bat in the header # write packet's id right off the bat in the header
VarInt.send(self.id, packet_buffer) VarInt.send(self.id, packet_buffer)
@ -125,6 +126,7 @@ class PingPacket(Packet):
definition = [ definition = [
{'time': Long}] {'time': Long}]
STATE_STATUS_CLIENTBOUND = { STATE_STATUS_CLIENTBOUND = {
0x00: ResponsePacket, 0x00: ResponsePacket,
0x01: PingPacket 0x01: PingPacket
@ -143,6 +145,7 @@ class PingPacket(Packet):
definition = [ definition = [
{'time': Long}] {'time': Long}]
STATE_STATUS_SERVERBOUND = { STATE_STATUS_SERVERBOUND = {
0x00: RequestPacket, 0x00: RequestPacket,
0x01: PingPacket 0x01: PingPacket
@ -181,6 +184,7 @@ class SetCompressionPacket(Packet):
definition = [ definition = [
{'threshold': VarInt}] {'threshold': VarInt}]
STATE_LOGIN_CLIENTBOUND = { STATE_LOGIN_CLIENTBOUND = {
0x00: DisconnectPacket, 0x00: DisconnectPacket,
0x01: EncryptionRequestPacket, 0x01: EncryptionRequestPacket,
@ -203,6 +207,7 @@ class EncryptionResponsePacket(Packet):
{'shared_secret': VarIntPrefixedByteArray}, {'shared_secret': VarIntPrefixedByteArray},
{'verify_token': VarIntPrefixedByteArray}] {'verify_token': VarIntPrefixedByteArray}]
STATE_LOGIN_SERVERBOUND = { STATE_LOGIN_SERVERBOUND = {
0x00: LoginStartPacket, 0x00: LoginStartPacket,
0x01: EncryptionResponsePacket 0x01: EncryptionResponsePacket
@ -295,8 +300,9 @@ class PositionAndLookPacket(Packet):
{'pitch': Float}, {'pitch': Float},
{'on_ground': Boolean}] {'on_ground': Boolean}]
STATE_PLAYING_SERVERBOUND = { STATE_PLAYING_SERVERBOUND = {
0x00: KeepAlivePacket, 0x00: KeepAlivePacket,
0x01: ChatPacket, 0x01: ChatPacket,
0x06: PositionAndLookPacket 0x06: PositionAndLookPacket
} }

View File

@ -115,24 +115,24 @@ class VarInt(Type):
@staticmethod @staticmethod
def size(value): def size(value):
for max_value, size in VARINT_SIZE_TABLE.iteritems(): for max_value, size in VARINT_SIZE_TABLE.items():
if value < max_value: if value < max_value:
return size return size
# Maps (maximum integer value -> size of VarInt in bytes) # Maps (maximum integer value -> size of VarInt in bytes)
VARINT_SIZE_TABLE = { VARINT_SIZE_TABLE = {
2**7: 1, 2 ** 7: 1,
2**14: 2, 2 ** 14: 2,
2**21: 3, 2 ** 21: 3,
2**28: 4, 2 ** 28: 4,
2**35: 5, 2 ** 35: 5,
2**42: 6, 2 ** 42: 6,
2**49: 7, 2 ** 49: 7,
2**56: 8, 2 ** 56: 8,
2**63: 9, 2 ** 63: 9,
2**70: 10, 2 ** 70: 10,
2**77: 11, 2 ** 77: 11,
2**84: 12 2 ** 84: 12
} }
@ -168,9 +168,8 @@ class Double(Type):
class ShortPrefixedByteArray(Type): class ShortPrefixedByteArray(Type):
@staticmethod @staticmethod
def read(file_object, length=None): def read(file_object):
if length is None: length = Short.read(file_object)
length = Short.read(file_object)
return struct.unpack(str(length) + "s", file_object.read(length))[0] return struct.unpack(str(length) + "s", file_object.read(length))[0]
@staticmethod @staticmethod
@ -181,9 +180,8 @@ class ShortPrefixedByteArray(Type):
class VarIntPrefixedByteArray(Type): class VarIntPrefixedByteArray(Type):
@staticmethod @staticmethod
def read(file_object, length=None): def read(file_object):
if length is None: length = VarInt.read(file_object)
length = VarInt.read(file_object)
return struct.unpack(str(length) + "s", file_object.read(length))[0] return struct.unpack(str(length) + "s", file_object.read(length))[0]
@staticmethod @staticmethod
@ -196,10 +194,10 @@ class String(Type):
@staticmethod @staticmethod
def read(file_object): def read(file_object):
length = VarInt.read(file_object) length = VarInt.read(file_object)
return unicode(file_object.read(length), "utf-8") return file_object.read(length).decode("utf-8")
@staticmethod @staticmethod
def send(value, socket): def send(value, socket):
value = unicode(value).encode('utf-8') value = str(value).encode('utf-8')
VarInt.send(len(value), socket) VarInt.send(len(value), socket)
socket.send(value) socket.send(value)

View File

@ -9,8 +9,7 @@ class Hashing(unittest.TestCase):
'simon': '88e16a1019277b15d58faf0541e11910eb756f6'} 'simon': '88e16a1019277b15d58faf0541e11910eb756f6'}
def test_hashing(self): def test_hashing(self):
for input_value in self.test_data.iterkeys(): for input_value, result in self.test_data.items():
sha1_hash = hashlib.sha1() sha1_hash = hashlib.sha1()
sha1_hash.update(input_value) sha1_hash.update(input_value.encode('utf-8'))
self.assertEquals(minecraft_sha1_hash_digest(sha1_hash), self.assertEquals(minecraft_sha1_hash_digest(sha1_hash), result)
self.test_data[input_value])