Added more docstrings, edited readme

This commit is contained in:
Lonami 2016-08-28 10:38:46 +02:00
parent f00329265d
commit 5af1a4a5fc
4 changed files with 48 additions and 18 deletions

3
.gitignore vendored
View File

@ -1,4 +1,7 @@
.idea .idea
tl/functions/
tl/types/
tl/all_tlobjects.py
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

View File

@ -1,5 +1,7 @@
import tlobjects_generator import tl.generator
if __name__ == '__main__': if __name__ == '__main__':
tlobjects_generator.generate_tlobjecs() if not tl.generator.tlobjects_exist():
print('Please run tl/generator.py at least once before continuing')
else:
pass

View File

@ -1,17 +1,36 @@
import os import os
import re import re
import shutil
from parser.tl_parser import TLParser from parser.tl_parser import TLParser
from parser.source_builder import SourceBuilder from parser.source_builder import SourceBuilder
def generate_tlobjecs(): def tlobjects_exist():
"""Determines whether the TLObjects were previously generated (hence exist) or not"""
return os.path.isfile('tl/all_tlobjects.py')
def clean_tlobjects():
"""Cleans the automatically generated TLObjects from disk"""
if os.path.isdir('tl/functions'):
shutil.rmtree('tl/functions')
if os.path.isdir('tl/types'):
shutil.rmtree('tl/types')
if os.path.isfile('tl/all_tlobjects.py'):
os.remove('tl/all_tlobjects.py')
def generate_tlobjects(scheme_file):
"""Generates all the TLObjects from scheme.tl to tl/functions and tl/types""" """Generates all the TLObjects from scheme.tl to tl/functions and tl/types"""
# First ensure that the required parent directories exist # First ensure that the required parent directories exist
os.makedirs('tl/functions', exist_ok=True) os.makedirs('tl/functions', exist_ok=True)
os.makedirs('tl/types', exist_ok=True) os.makedirs('tl/types', exist_ok=True)
tlobjects = tuple(TLParser.parse_file('scheme.tl')) # Store the parsed file in a tuple for iterating it more than once
tlobjects = tuple(TLParser.parse_file(scheme_file))
for tlobject in tlobjects: for tlobject in tlobjects:
# Determine the output directory and create it # Determine the output directory and create it
out_dir = os.path.join('tl', out_dir = os.path.join('tl',
@ -23,12 +42,12 @@ def generate_tlobjecs():
os.makedirs(out_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True)
init_py = os.path.join(out_dir, '__init__.py')
# Also create __init__.py # Also create __init__.py
init_py = os.path.join(out_dir, '__init__.py')
if not os.path.isfile(init_py): if not os.path.isfile(init_py):
open(init_py, 'a').close() open(init_py, 'a').close()
# Create the file # Create the file for this TLObject
filename = os.path.join(out_dir, get_file_name(tlobject, add_extension=True)) filename = os.path.join(out_dir, get_file_name(tlobject, add_extension=True))
with open(filename, 'w', encoding='utf-8') as file: with open(filename, 'w', encoding='utf-8') as file:
# Let's build the source code! # Let's build the source code!
@ -83,12 +102,12 @@ def generate_tlobjecs():
if tlobject.is_function: if tlobject.is_function:
builder.writeln('self.result = None') builder.writeln('self.result = None')
# Leave an empty line if there are any args # Set the arguments
if args: if args:
# Leave an empty line if there are any args
builder.writeln() builder.writeln()
for arg in args:
for arg in args: builder.writeln('self.{0} = {0}'.format(arg.name))
builder.writeln('self.{0} = {0}'.format(arg.name))
builder.end_block() builder.end_block()
# Write the on_send(self, writer) function # Write the on_send(self, writer) function
@ -110,6 +129,7 @@ def generate_tlobjecs():
for arg in tlobject.args: for arg in tlobject.args:
write_onresponse_code(builder, arg, tlobject.args) write_onresponse_code(builder, arg, tlobject.args)
else: else:
# If there were no arguments, we still need an on_response method, and hence "pass" if empty
builder.writeln('pass') builder.writeln('pass')
builder.end_block() builder.end_block()
@ -129,18 +149,18 @@ def generate_tlobjecs():
builder.writeln('tlobjects = {') builder.writeln('tlobjects = {')
builder.current_indent += 1 builder.current_indent += 1
# Fill the dictionary (0x1a2b3c4f: tl.full.type.path.Class)
for tlobject in tlobjects: for tlobject in tlobjects:
builder.writeln('{}: {}.{},'.format( builder.writeln('{}: {}.{},'
hex(tlobject.id), .format(hex(tlobject.id), get_full_file_name(tlobject), get_class_name(tlobject)))
get_full_file_name(tlobject),
get_class_name(tlobject)
))
builder.current_indent -= 1 builder.current_indent -= 1
builder.writeln('}') builder.writeln('}')
def get_class_name(tlobject): def get_class_name(tlobject):
"""Gets the class name following the Python style guidelines, in ThisClassFormat"""
# Courtesy of http://stackoverflow.com/a/31531797/4759433 # Courtesy of http://stackoverflow.com/a/31531797/4759433
# Also, '_' could be replaced for ' ', then use .title(), and then remove ' ' # Also, '_' could be replaced for ' ', then use .title(), and then remove ' '
result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), tlobject.name) result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), tlobject.name)
@ -148,6 +168,8 @@ def get_class_name(tlobject):
def get_full_file_name(tlobject): def get_full_file_name(tlobject):
"""Gets the full file name for the given TLObject (tl.type.full.path)"""
fullname = get_file_name(tlobject, add_extension=False) fullname = get_file_name(tlobject, add_extension=False)
if tlobject.namespace is not None: if tlobject.namespace is not None:
fullname = '{}.{}'.format(tlobject.namespace, fullname) fullname = '{}.{}'.format(tlobject.namespace, fullname)
@ -159,6 +181,8 @@ def get_full_file_name(tlobject):
def get_file_name(tlobject, add_extension): def get_file_name(tlobject, add_extension):
"""Gets the file name in file_name_format.py for the given TLObject"""
# Courtesy of http://stackoverflow.com/a/1176023/4759433 # Courtesy of http://stackoverflow.com/a/1176023/4759433
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', tlobject.name) s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', tlobject.name)
result = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() result = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
@ -324,5 +348,6 @@ def write_onresponse_code(builder, arg, args, name=None):
builder.end_block() builder.end_block()
def get_code(tg_type, stream_name, arg_name): if __name__ == '__main__':
function_name = 'write' if stream_name == 'writer' else 'read' clean_tlobjects()
generate_tlobjects('scheme.tl')