From b3ca68b7d9cc7a100a9ba4550c0de442146865f4 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Tue, 24 Oct 2017 10:07:31 +0200 Subject: [PATCH] Avoid cyclic imports caused by #348 (fix #357) --- telethon_generator/error_generator.py | 3 +-- telethon_generator/parser/tl_object.py | 3 +-- telethon_generator/tl_generator.py | 26 +++++++++++++++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/telethon_generator/error_generator.py b/telethon_generator/error_generator.py index feb32b5a..30163dfc 100644 --- a/telethon_generator/error_generator.py +++ b/telethon_generator/error_generator.py @@ -154,11 +154,10 @@ def generate_code(output, json_file, errors_desc): patterns.append((pattern, name)) capture = capture_names.get(name, 'x') if has_captures else None # TODO Some errors have the same name but different code, - # split this accross different files? + # split this across different files? write_error(f, error_code, name, description, capture) f.write('\n\nrpc_errors_all = {\n') for pattern, name in patterns: f.write(' {}: {},\n'.format(repr(pattern), name)) f.write('}\n') - diff --git a/telethon_generator/parser/tl_object.py b/telethon_generator/parser/tl_object.py index 79b4385d..278a66eb 100644 --- a/telethon_generator/parser/tl_object.py +++ b/telethon_generator/parser/tl_object.py @@ -104,8 +104,7 @@ class TLObject: def class_name_for(typename, is_function=False): """Gets the class name following the Python style guidelines""" # Courtesy of http://stackoverflow.com/a/31531797/4759433 - result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), - typename) + result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), typename) result = result[:1].upper() + result[1:].replace('_', '') # If it's a function, let it end with "Request" to identify them if is_function: diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index f0a14fbc..b5d43656 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -129,11 +129,6 @@ class TLGenerator: builder.writeln( 'from {}.tl.tlobject import TLObject'.format('.' * depth) ) - if ns: - # Only import the parent types if we're not in such file - builder.writeln( - 'from {}.tl import types'.format('.' * depth) - ) # Add the relative imports to the namespaces, # unless we already are in a namespace. @@ -646,8 +641,25 @@ class TLGenerator: if not arg.skip_constructor_id: builder.writeln('{} = reader.tgread_object()'.format(name)) else: - builder.writeln('{} = types.{}.from_reader(reader)'.format( - name, TLObject.class_name_for(arg.type))) + # Import the correct type inline to avoid cyclic imports. + # There may be better solutions so that we can just access + # all the types before the files have been parsed, but I + # don't know of any. + sep_index = arg.type.find('.') + if sep_index == -1: + ns, t = '.', arg.type + else: + ns, t = '.' + arg.type[:sep_index], arg.type[sep_index+1:] + class_name = TLObject.class_name_for(t) + + # There would be no need to import the type if we're in the + # file with the same namespace, but since it does no harm + # and we don't have information about such thing in the + # method we just ignore that case. + builder.writeln('from {} import {}'.format(ns, class_name)) + builder.writeln('{} = {}.from_reader(reader)'.format( + name, class_name + )) # End vector and flag blocks if required (if we opened them before) if arg.is_vector: