From 8da6ffd7d5b1d1f25623076c65ff175c5def9d51 Mon Sep 17 00:00:00 2001 From: singer Date: Thu, 19 Oct 2017 18:47:55 +0300 Subject: [PATCH 1/3] Fixing python 3.4 compatibility support. Possible issue with circular imports (https://docs.python.org/3/whatsnew/3.5.html#other-language-changes) which is handled ok it 3.5+ and is giving an error in 3.4 --- telethon/crypto/auth_key.py | 4 ++-- telethon/telegram_bare_client.py | 7 ++++--- telethon_generator/tl_generator.py | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/telethon/crypto/auth_key.py b/telethon/crypto/auth_key.py index 17a7f8ca..7dce3fa3 100644 --- a/telethon/crypto/auth_key.py +++ b/telethon/crypto/auth_key.py @@ -1,7 +1,7 @@ import struct from hashlib import sha1 -from .. import helpers as utils +from ..helpers import calc_msg_key from ..extensions import BinaryReader @@ -20,4 +20,4 @@ class AuthKey: """ new_nonce = new_nonce.to_bytes(32, 'little', signed=True) data = new_nonce + struct.pack(' 10 * 1024 * 1024 part_count = (file_size + part_size - 1) // part_size - file_id = utils.generate_random_long() + file_id = generate_random_long() hash_md5 = md5() stream = open(file, 'rb') if isinstance(file, str) else BytesIO(file) @@ -678,7 +679,7 @@ class TelegramBareClient: if isinstance(file, str): # Ensure that we'll be able to download the media - utils.ensure_parent_dir_exists(file) + ensure_parent_dir_exists(file) f = open(file, 'wb') else: f = file diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index 8fc6bb2d..81596e01 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -127,10 +127,10 @@ class TLGenerator: # so they all can be serialized and sent, however, only the # functions are "content_related". builder.writeln( - 'from {}.tl.tlobject import TLObject'.format('.' * depth) + 'from telethon.tl.tlobject import TLObject'.format('.' * depth) ) builder.writeln( - 'from {}.tl import types'.format('.' * depth) + 'import telethon.tl.types'.format('.' * depth) ) # Add the relative imports to the namespaces, From b072caae09a3f7120b713b769eccf9fce1c9d446 Mon Sep 17 00:00:00 2001 From: singer Date: Fri, 20 Oct 2017 12:35:03 +0300 Subject: [PATCH 2/3] Removing circular imports in autogenerated files. --- telethon/network/authenticator.py | 4 ++-- telethon_generator/tl_generator.py | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/telethon/network/authenticator.py b/telethon/network/authenticator.py index 1accf493..f4f30fa9 100644 --- a/telethon/network/authenticator.py +++ b/telethon/network/authenticator.py @@ -6,7 +6,7 @@ from ..tl.types import ( ResPQ, PQInnerData, ServerDHParamsFail, ServerDHParamsOk, ServerDHInnerData, ClientDHInnerData, DhGenOk, DhGenRetry, DhGenFail ) -from .. import helpers as utils +from ..helpers import generate_key_data_from_nonce from ..crypto import AES, AuthKey, Factorization from ..crypto import rsa from ..errors import SecurityError @@ -110,7 +110,7 @@ def _do_authentication(connection): raise SecurityError('Invalid server nonce from server') # Step 3 sending: Complete DH Exchange - key, iv = utils.generate_key_data_from_nonce( + key, iv = generate_key_data_from_nonce( res_pq.server_nonce, new_nonce ) plain_text_answer = AES.decrypt_ige( diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index 81596e01..a524ca7b 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -117,8 +117,18 @@ class TLGenerator: def _write_init_py(out_dir, depth, namespace_tlobjects, type_constructors): # namespace_tlobjects: {'namespace', [TLObject]} os.makedirs(out_dir, exist_ok=True) + + # Generate __init__.py with relative imports to the namespaces + with open(os.path.join(out_dir, '__init__.py'), 'w', encoding='utf-8') as f, \ + SourceBuilder(f) as builder: + builder.writeln(AUTO_GEN_NOTICE) + builder.writeln('from . import {}'.format(', '.join( + x for x in namespace_tlobjects.keys() if x + ))) + builder.writeln('from .base import *') + for ns, tlobjects in namespace_tlobjects.items(): - file = os.path.join(out_dir, ns + '.py' if ns else '__init__.py') + file = os.path.join(out_dir, ns + '.py' if ns else 'base.py') with open(file, 'w', encoding='utf-8') as f, \ SourceBuilder(f) as builder: builder.writeln(AUTO_GEN_NOTICE) @@ -127,18 +137,8 @@ class TLGenerator: # so they all can be serialized and sent, however, only the # functions are "content_related". builder.writeln( - 'from telethon.tl.tlobject import TLObject'.format('.' * depth) + 'from {}.tl.tlobject import TLObject'.format('.' * depth) ) - builder.writeln( - 'import telethon.tl.types'.format('.' * depth) - ) - - # Add the relative imports to the namespaces, - # unless we already are in a namespace. - if not ns: - builder.writeln('from . import {}'.format(', '.join( - x for x in namespace_tlobjects.keys() if x - ))) # Import 'get_input_*' utils # TODO Support them on types too @@ -644,7 +644,8 @@ class TLGenerator: if not arg.skip_constructor_id: builder.writeln('{} = reader.tgread_object()'.format(name)) else: - builder.writeln('{} = types.{}.from_reader(reader)'.format( + builder.writeln('from . import {}'.format(TLObject.class_name_for(arg.type))) + builder.writeln('{} = {}.from_reader(reader)'.format( name, TLObject.class_name_for(arg.type))) # End vector and flag blocks if required (if we opened them before) From 28337364842a7c4d7d13cb2ee8e0cbd80a4be213 Mon Sep 17 00:00:00 2001 From: singer Date: Fri, 20 Oct 2017 15:19:01 +0300 Subject: [PATCH 3/3] Fix to avoid imports every from_reader() is called --- telethon_generator/tl_generator.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index a524ca7b..4838087c 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -6,6 +6,7 @@ from zlib import crc32 from collections import defaultdict from .parser import SourceBuilder, TLParser, TLObject + AUTO_GEN_NOTICE = \ '"""File generated by TLObjects\' generator. All changes will be ERASED"""' @@ -140,6 +141,12 @@ class TLGenerator: 'from {}.tl.tlobject import TLObject'.format('.' * depth) ) + # No need to import base in base.py + if ns: + builder.writeln( + 'from . import base' + ) + # Import 'get_input_*' utils # TODO Support them on types too if 'functions' in out_dir: @@ -343,7 +350,7 @@ class TLGenerator: builder.writeln('def from_reader(reader):') for arg in tlobject.args: TLGenerator.write_read_code( - builder, arg, tlobject.args, name='_' + arg.name + builder, arg, tlobject, name='_' + arg.name ) builder.writeln('return {}({})'.format( @@ -550,15 +557,14 @@ class TLGenerator: return True # Something was written @staticmethod - def write_read_code(builder, arg, args, name): + def write_read_code(builder, arg, tlobject, name): """ Writes the read code for the given argument, setting the arg.name variable to its read value. :param builder: The source code builder :param arg: The argument to write - :param args: All the other arguments in TLObject same on_send. - This is required to determine the flags value + :param tlobject: The TLObject for which from_reader() method is written :param name: The name of the argument. Defaults to "self.argname" This argument is an option because it's required when writing Vectors<> @@ -595,7 +601,7 @@ class TLGenerator: builder.writeln('for _ in range(reader.read_int()):') # Temporary disable .is_vector, not to enter this if again arg.is_vector = False - TLGenerator.write_read_code(builder, arg, args, name='_x') + TLGenerator.write_read_code(builder, arg, tlobject, name='_x') builder.writeln('{}.append(_x)'.format(name)) arg.is_vector = True @@ -644,9 +650,8 @@ class TLGenerator: if not arg.skip_constructor_id: builder.writeln('{} = reader.tgread_object()'.format(name)) else: - builder.writeln('from . import {}'.format(TLObject.class_name_for(arg.type))) - builder.writeln('{} = {}.from_reader(reader)'.format( - name, TLObject.class_name_for(arg.type))) + builder.writeln('{} = {}{}.from_reader(reader)'.format( + name, 'base.' if tlobject.namespace else '', TLObject.class_name_for(arg.type))) # End vector and flag blocks if required (if we opened them before) if arg.is_vector: