Created
August 3, 2016 15:04
-
-
Save RossRogers/aa0f3489383575a3fe414c0749a26d2a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.core.management.base import BaseCommand, CommandError | |
from django.conf import settings | |
import rest_framework | |
from collections import namedtuple | |
import re,sys | |
INDENT = ' '*2 | |
# TODO(rrogers) 2015.06.01 - allow canonical, global nested-objects and | |
# automatically swap them in? | |
# | |
# If a model is marked as globally_canonical, then 1 and only 1 version of that | |
# model exists | |
# | |
# * post_restore on such an object should register its `url` globally and | |
# anyone wishing to get a reference should look in the hash | |
# | |
# * should updates from the server be golden? or should local state take | |
# precedence? | |
# | |
# * fields referencing canonical objects have a property in the place of | |
# reference url fields in order to spoof out and obviate the need for | |
# manual field obj/url alias sync'ing. | |
# | |
class Command(BaseCommand): | |
help = 'Generates a js interface from the Rest Framework serializers' | |
def add_arguments(self, parser): | |
parser.add_argument('output_path', nargs='+', type=str) | |
parser.add_argument('base_factory_name', nargs='+', type=str) | |
parser.add_argument('server_base_url', nargs='+', type=str) | |
def handle(self, *args, **options): | |
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver | |
from django.utils.termcolors import colorize | |
import os, sys | |
(output_path,base_factory_name) = args[:2] | |
server_base_url = args[2] if len(args) > 2 else '/rest' | |
server_base_url = server_base_url.rstrip('/')+'/' | |
from qc_srvr.urls import urlpatterns | |
serializer_2_class = {} | |
ClassDefn = namedtuple('ClassDefn',('url_name','fields','meta')) | |
FieldDefn = namedtuple('FieldDefn',('field_name','type','meta','instance_class_name')) | |
def traverse(url_patterns, prefix=''): | |
for p in url_patterns: | |
if isinstance(p, RegexURLPattern): | |
composed = '%s%s' % (prefix, p.regex.pattern) | |
#print '\t%s' % (composed), '==> ' | |
#sys.stdout.write('%s.' % p.callback.__module__) | |
viewset = getattr(p.callback,'cls',None) | |
if not viewset: | |
continue | |
viewset = viewset() # create instance | |
if not isinstance(viewset,rest_framework.viewsets.ModelViewSet): | |
continue | |
serializer_class = getattr(viewset,'serializer_class',None) | |
if not serializer_class: | |
continue | |
serializer = serializer_class() | |
model = getattr(serializer.Meta,'model') | |
full_serializer_type = serializer.__module__+'.'+serializer.__class__.__name__ | |
url = re.compile(r'^\^*((?:\w+/?)+)').search(composed).group(1) | |
url_name = url.strip('/').split('/') | |
class_defn = ClassDefn(url_name,[],{}) | |
class_defn.meta['url'] = server_base_url + url | |
class_defn.meta['is_list_class'] = p.callback.suffix == 'List' | |
if class_defn.meta['is_list_class']: | |
class_defn.meta['instance_class_name'] = url_name[-1] | |
# class_defn.meta['instance_class_full_name'] = base_factory_name + '.' + '.'.join(url_name) | |
if p.callback.suffix == 'List': | |
url_name[-1] += p.callback.suffix | |
full_serializer_type += p.callback.suffix | |
if full_serializer_type in serializer_2_class: | |
pass | |
# if -1 != composed.find('PackingInstr/'): | |
# import rpdb2;rpdb2.start_embedded_debugger('foo') | |
# print 'WARNING: entry',full_serializer_type,'already exists in serializer_2_class. \n\told defn:',serializer_2_class[full_serializer_type],'\n\tnew defn:',class_defn | |
serializer_2_class[full_serializer_type] = class_defn | |
model_fields = {} | |
for field in sorted(model._meta.concrete_fields + model._meta.many_to_many + model._meta.virtual_fields): | |
model_fields[field.name] = field | |
if class_defn.meta['is_list_class']: | |
def a(f): | |
class_defn.fields.append(f) | |
#a(FieldDefn('count','number',{'is_integer':True},None)) | |
#a(FieldDefn('next','string',{},None)) | |
#a(FieldDefn('previous','string',{},None)) | |
f = FieldDefn('results','Array< '+class_defn.meta['instance_class_name'] + ' >',{},class_defn.meta['instance_class_name']) | |
class_defn.fields.append(f) | |
else : | |
#DRF3.+for f_name,f in serializer.fields.fields.iteritems(): | |
for f_name,f in serializer.fields.iteritems(): | |
t = None | |
field_meta = {} | |
# DRF3.+if isinstance(f,rest_framework.relations.ManyRelatedField): | |
if isinstance(f,rest_framework.relations.RelatedField): | |
#import rpdb2;rpdb2.start_embedded_debugger('foo') | |
f = getattr(serializer_class,f_name,f) | |
# DRF3.+ | |
# many = isinstance(f,rest_framework.serializers.ListSerializer) or isinstance(f,rest_framework.relations.ManyRelatedField) | |
# if isinstance(f,rest_framework.serializers.ListSerializer): | |
# f = getattr(f,'child',f) | |
# f.many = many | |
f.many = getattr(f,'many',False) | |
# if f_name == 'header_sample_requirements': | |
# import rpdb2;rpdb2.start_embedded_debugger('foo') | |
#print f_name | |
#if f_name.endswith('user_permissions'): | |
# import rpdb2;rpdb2.start_embedded_debugger('foo') | |
if isinstance(f,rest_framework.fields.BooleanField): t = 'boolean' | |
elif isinstance(f,rest_framework.fields.CharField): t = 'String' | |
elif isinstance(f,rest_framework.fields.URLField): t = 'String' | |
elif isinstance(f,rest_framework.fields.SlugField): t = 'String' | |
elif isinstance(f,rest_framework.fields.ChoiceField): t = 'String' | |
elif isinstance(f,rest_framework.fields.EmailField): t = 'String' | |
elif isinstance(f,rest_framework.fields.RegexField): t = 'String' | |
elif isinstance(f,rest_framework.fields.DateField): | |
t = 'Date' | |
field_meta['is_date_only_field'] = True | |
elif isinstance(f,rest_framework.fields.DateTimeField): t = 'Date' | |
elif isinstance(f,rest_framework.fields.TimeField): | |
t = 'Date' | |
field_meta.is_time_only_field | |
elif isinstance(f,rest_framework.fields.IntegerField): | |
t = 'number' | |
field_meta['is_integer'] = True | |
elif isinstance(f,rest_framework.fields.FloatField): t = 'number' | |
elif isinstance(f,rest_framework.fields.DecimalField): t = 'number' | |
elif isinstance(f,rest_framework.relations.HyperlinkedIdentityField): t = 'String' | |
elif isinstance(f,rest_framework.relations.HyperlinkedRelatedField): | |
t = 'String' | |
field_meta['is_url'] = True | |
elif isinstance(f,rest_framework.relations.PrimaryKeyRelatedField): | |
t = 'number' | |
field_meta['is_integer'] = True | |
elif isinstance(f,rest_framework.serializers.Serializer): | |
def getter(module_name,many): | |
def inner(): | |
return ('Array< ' if many else '')+\ | |
base_factory_name + '.' + \ | |
'.'.join(serializer_2_class[module_name].url_name) +\ | |
(' >' if many else '') | |
return inner | |
field_meta['field_is_delegate_serializer'] = True | |
if f.many: | |
field_meta['is_array'] = True | |
field_meta['inst_type'] = getter(f.__module__+'.'+f.__class__.__name__,False) | |
t = getter(f.__module__+'.'+f.__class__.__name__,f.many) | |
elif isinstance(f,rest_framework.serializers.Field): t = 'String' | |
else: | |
print >>sys.stderr, "ERROR: Couldn't figure out field",f_name,"for serializer",full_serializer_type | |
t = 'String' | |
if getattr(f,'many',False) and not isinstance(f,rest_framework.serializers.Serializer): | |
field_meta['is_array'] = True | |
field_meta['inst_type'] = t | |
t = 'Array< '+t +' >' | |
wo = getattr(serializer.Meta,'write_only_fields', None) | |
if wo and f_name in wo: | |
field_meta['is_write_only'] = True | |
if not t: | |
raise Exception() | |
# import rpdb2;rpdb2.start_embedded_debugger('foo') | |
class_defn.fields.append(FieldDefn(f_name,t,field_meta,None)) | |
if isinstance(p, RegexURLResolver): | |
traverse(p.url_patterns, prefix=p.regex.pattern) | |
traverse(urlpatterns) | |
#import rpdb2;rpdb2.start_embedded_debugger('foo') | |
base_module = {} | |
print '' | |
for serializer_name, cls in serializer_2_class.iteritems(): | |
module = base_module | |
for u in cls.url_name[:-1]: | |
module = module.setdefault(u,{}) | |
module[cls.url_name[-1]] = cls | |
#print serializer_name, '.'.join(cls.url_name) | |
for f in cls.fields: | |
pass | |
#print ' ',f.field_name,':',(f.type() if callable(f.type) else f.type) | |
#print len(cls.fields) | |
out = open(output_path,'w') if len(args) > 0 else sys.stdout | |
def w(s): | |
out.write(s) | |
out.write('\n') | |
w("'use strict';") | |
w('// jshint newcap:false') | |
w('/*jshint -W040 */') | |
w('function pad2(num) {') | |
w(INDENT + "return ('0'+num).slice(-2);") | |
w('}') | |
w('var TIMEZONE_OFFSET = new Date().getTimezoneOffset();') | |
w('/* jshint ignore:start */') | |
w('var TIMEZONE_OFFSET_MS = TIMEZONE_OFFSET*60*1000;') | |
w('var TIMEZONE_OFFSET_MS_PADDED = (TIMEZONE_OFFSET+12*60)*60*1000;') | |
w('/* jshint ignore:end */') | |
w("var TIMEZONE_ISO_TIME = 'T' + pad2(TIMEZONE_OFFSET/60 + 12) +") | |
w(INDENT + "':' + pad2(TIMEZONE_OFFSET%60) + ':00.000Z';") | |
w('') | |
w('var '+base_factory_name+' = {};') | |
w('(function ('+base_factory_name+') {') | |
w(''' | |
function gen_list_get(base_url,Cls,InstClass) { | |
return function(parameters, config, destination) { | |
var url = base_url; | |
if (parameters) { url += '?'+parameters; } | |
destination = destination || new Cls(); | |
var post_restore_intercept = function(data) { | |
var d = data.data; | |
destination.count = parseInt(d.count); | |
destination.next = d.next; | |
destination.previous = d.previous; | |
destination.results = []; | |
var list_element_promises = []; | |
d.results.forEach(function(_,i) { | |
var element_promise = InstClass.post_restore(d.results[i]); | |
list_element_promises.push(element_promise); | |
destination.results.push(element_promise); | |
element_promise.then(function(el) { destination.results[i] = el; }); | |
}); | |
if (list_element_promises.length) { | |
return ''' + base_factory_name + '''.$q.all(list_element_promises).then(function(){ return destination; }); | |
} else { | |
return destination; | |
} | |
}; | |
config = config || {} | |
return ''' + base_factory_name + '''.$http.get(url,config).then(post_restore_intercept); | |
}; | |
} | |
function gen_inst_save(url, Cls) { | |
return function() { | |
var req_defer = ''' + base_factory_name + '''.$q.defer(); | |
var self = this; | |
this.pre_save().then(function(saver) { | |
var promise; | |
if ('url' in saver) { | |
promise = ''' + base_factory_name + '''.$http.put(saver.url, saver); | |
} else if ('id' in saver) { | |
promise = ''' + base_factory_name + '''.$http.put(self.base_url + saver.id + '/', saver); | |
} else { | |
promise = ''' + base_factory_name + '''.$http.post(url, saver); | |
} | |
promise = promise.then(function(data) { | |
return Cls.post_restore(data.data,self); | |
}); | |
promise.catch('''+base_factory_name+'''.log_http_error); | |
req_defer.resolve(promise); | |
}); | |
return req_defer.promise; | |
}; | |
} | |
function gen_inst_get(base_url, Cls) { | |
return function(pk, destination) { | |
destination = destination || new Cls(); | |
var post_restore_intercept = function(data) { | |
return Cls.post_restore(data.data, destination); | |
}; | |
var url = /^\w+$/.test(pk) ? base_url + pk + '/' : pk; | |
var promise = ''' + base_factory_name + '''.$http.get(url) | |
.then(post_restore_intercept); | |
promise.catch(''' + base_factory_name + '''.log_http_error); | |
return promise; | |
}; | |
} | |
function gen_inst_delete(url, Cls) { | |
return function() { | |
if (this.url) { | |
return ''' + base_factory_name + '''.$http.delete(this.url); | |
} else if (this.id) { | |
return ''' + base_factory_name + '''.$http.delete(this.base_url + this.id + '/'); | |
} else { | |
return ''' + base_factory_name + '''.$q.when(null); | |
} | |
}; | |
} | |
''') | |
def OutputClasses(module,module_names=[],indent=''): | |
def keep_list_close_to_inst_cmp(a,b): | |
a_stripped = a | |
a_is_list = a[-4:] == 'List' | |
if a_is_list: | |
a_stripped = a[:-4] | |
b_stripped = b | |
b_is_list = b[-4:] == 'List' | |
if b_is_list: | |
b_stripped = b[:-4] | |
if a_stripped == b_stripped: | |
return cmp(a,b) | |
return cmp(a_stripped,b_stripped) | |
keys = sorted(module.keys(),keep_list_close_to_inst_cmp) | |
factory_lines = [] | |
indent_child = indent + INDENT | |
for mod_class_name in keys: | |
mod_class = module[mod_class_name] | |
if isinstance(mod_class,ClassDefn): | |
cls = mod_class | |
cls_name = mod_class_name | |
indent_g_child = indent_child + INDENT | |
indent_gg_child = indent_child + 2 * INDENT | |
indent_ggg_child = indent_child + 3 * INDENT | |
indent_gggg_child = indent_child + 4 * INDENT | |
indent_ggggg_child = indent_child + 5 * INDENT | |
indent_gggggg_child = indent_child + 6 * INDENT | |
encapsulating_module = module_names[-1] | |
w(indent_child + encapsulating_module +'.' + cls_name + ' = (function() {') | |
w('') | |
len_longest_field_name = reduce(lambda accum,f: max(accum,len(f.field_name)),cls.fields,0) | |
field_name_formatter = '%%-%ds'%len_longest_field_name | |
if cls.meta['is_list_class']: | |
w(indent_g_child + 'function '+cls_name+'() {') | |
# w(indent_gg_child + 'this.count = null') | |
# w(indent_gg_child + 'this.next = null') | |
# w(indent_gg_child + 'this.previous = null') | |
w(indent_gg_child + 'this.results = [];') | |
w(indent_g_child +'}') | |
w('') | |
w(indent_g_child + cls_name + '.get = gen_list_get(\'' + cls.meta['url'] +'\', ' + cls_name + ', ' + encapsulating_module+'.'+cls.meta['instance_class_name'] + ');') | |
# w(indent_g_child + cls_name + '.get = function(parameters, config, destination) {') | |
# w(indent_gg_child + "var url = '" + cls.meta['url'] + "';") | |
# w(indent_gg_child + "if (parameters) { url += '?'+parameters; }") | |
# w(indent_gg_child + 'destination = destination || new '+cls_name+'();') | |
# w(indent_gg_child + 'var post_restore_intercept = function(data) {') | |
# w(indent_ggg_child + 'var d = data.data;') | |
# w(indent_ggg_child + 'destination.count = parseInt(d.count);') | |
# w(indent_ggg_child + 'destination.next = d.next;') | |
# w(indent_ggg_child + 'destination.previous = d.previous;') | |
# w(indent_ggg_child + 'destination.results = [];') | |
# w(indent_ggg_child + 'var list_element_promises = [];') | |
# w(indent_ggg_child + 'd.results.forEach(function(_,i) {') | |
# w(indent_gggg_child + 'var element_promise = ' + encapsulating_module+'.'+cls.meta['instance_class_name'] + '.post_restore(d.results[i]);') | |
# w(indent_gggg_child + 'list_element_promises.push(element_promise);') | |
# w(indent_gggg_child + 'destination.results.push(element_promise);') | |
# w(indent_gggg_child + 'element_promise.then(function(el) { destination.results[i] = el; });') | |
# w(indent_ggg_child + '});') | |
# w(indent_ggg_child + 'if (list_element_promises.length) {') | |
# w(indent_gggg_child + 'return ' + base_factory_name + '.$q.all(list_element_promises).then(function(){ return destination; });') | |
# w(indent_ggg_child + '} else {') | |
# w(indent_gggg_child + 'return destination;') | |
# w(indent_ggg_child + '}') | |
# w(indent_gg_child + '};') | |
# w(indent_gg_child + "config = config || {};") | |
# w(indent_gg_child + 'return ' + base_factory_name + '.$http.get(url,config).then(post_restore_intercept);') | |
# w(indent_g_child + '};') | |
w(indent_g_child + cls_name + '.prototype.get = function(parameters, config) {') | |
w(indent_gg_child + 'return '+ cls_name + '.get(parameters, config, this);') | |
w(indent_g_child + '};') | |
else: | |
w(indent_g_child + 'function '+cls_name+'() {') | |
for f in cls.fields: | |
if 'is_array' in f.meta: | |
w(indent_gg_child + 'this.' + f.field_name + ' = [];') | |
else: | |
pass | |
# w(indent_gg_child + 'this.' + f.field_name + ' = null') | |
w(indent_g_child +'}') | |
w('') | |
w(indent_g_child + cls_name + ".prototype.base_url = '" + cls.meta['url'] + "';") | |
w('') | |
w(indent_g_child + cls_name+'.prototype.pre_save = function() {') | |
w(indent_gg_child + 'var self = this;') | |
w(indent_gg_child + 'return ' + base_factory_name + '.$q(function(resolve) {') | |
w(indent_ggg_child + 'var result = self;') | |
w(indent_ggg_child + 'var child_pre_save_promises = [];') | |
saving_a_clone = {'yup':False} | |
def ensure_cloned_result(indent=0): | |
if not saving_a_clone['yup']: | |
saving_a_clone['yup'] = True | |
w(indent_ggg_child + indent*INDENT + 'result = $.extend({},result);') | |
for f in cls.fields: | |
data_manipulation_func = None | |
if 'is_date_only_field' in f.meta: | |
ensure_cloned_result() | |
data_manipulation_func = lambda src, dest: 'if ('+src+' && '+src+'.toISOString) { ' + dest +' = '+ src + '.toISOString().slice(0,10);}' | |
elif 'field_is_delegate_serializer' in f.meta: | |
ensure_cloned_result() | |
def func(src, dest, extra_indent=''): | |
promise_name = 'p_' + str(next_inst_cnt.next()) | |
return ( | |
'if ('+src + ' && '+src+'.pre_save) {\n' + | |
extra_indent + indent_gggg_child + 'var ' + promise_name + ' = ' +dest + ' = ' + src + '.pre_save();\n' + | |
extra_indent + indent_gggg_child + 'child_pre_save_promises.push(' + promise_name + ');\n' + | |
extra_indent + indent_gggg_child + promise_name + '.then(function(promise_result){ ' + dest + '= promise_result; });\n' + | |
extra_indent + indent_ggg_child + '} else {\n' + | |
extra_indent + indent_gggg_child + dest + ' = ' + src + ';\n' + extra_indent + indent_gggg_child + '\n' + | |
extra_indent + indent_ggg_child + '}') | |
data_manipulation_func = func | |
if data_manipulation_func: | |
if 'is_array' in f.meta: | |
w(indent_ggg_child + 'result.'+f.field_name+' = [];') | |
w(indent_ggg_child + 'self.'+f.field_name + '.forEach( function(_,i) {') | |
w(indent_gggg_child + data_manipulation_func('self.'+f.field_name+'[i]','result.'+f.field_name+'[i]',INDENT)) | |
w(indent_ggg_child + '});') | |
else: | |
w(indent_ggg_child + data_manipulation_func('result.'+f.field_name,'result.'+f.field_name)) | |
w(indent_ggg_child + 'if (child_pre_save_promises.length) {') | |
w(indent_gggg_child + 'resolve(' + base_factory_name + '.$q.all(child_pre_save_promises).then(function() { return result;}));') | |
w(indent_ggg_child + '} else {') | |
w(indent_gggg_child + 'resolve(result);') | |
w(indent_ggg_child + '}') | |
w(indent_gg_child + '});') | |
w(indent_g_child + '};') | |
w('') | |
w(indent_g_child + cls_name+'.post_restore = function(json_obj, destination) {') | |
w(indent_gg_child + 'return ' + base_factory_name + '.$q( function(resolve) {') | |
w(indent_ggg_child + 'var result = destination || new ' + cls_name + '(); // jshint ignore:line') | |
w(indent_ggg_child + 'if (json_obj === null) {') | |
w(indent_gggg_child + 'result = json_obj;') | |
w(indent_gggg_child + 'resolve(result);') | |
w(indent_ggg_child + '}') | |
w(indent_ggg_child + "if (typeof(json_obj) === 'undefined') {") | |
w(indent_gggg_child + 'resolve(result);') | |
w(indent_ggg_child + '}') | |
w(indent_ggg_child + 'var child_post_resolve_promises = [];') | |
def next_inst_cnt(): | |
inst_cnt = 0 | |
for i in xrange(0,1<<20): | |
inst_cnt += 1 | |
yield inst_cnt | |
next_inst_cnt = next_inst_cnt() | |
for f in cls.fields: | |
if 'is_write_only' in f.meta: | |
continue | |
t = f.type() if callable(f.type) else f.type | |
inst_type = t | |
if 'is_array' in f.meta: | |
inst_type = f.meta['inst_type'] | |
if callable(inst_type): | |
inst_type = inst_type() | |
data_manipulation_func = None | |
if 'is_date_only_field' in f.meta: | |
data_manipulation_func = lambda src,dest: 'if ('+src+" && (typeof("+dest+") === 'undefined' || "+dest+" === null)) { "+ dest + ' = new Date('+src+'+TIMEZONE_ISO_TIME); }' | |
elif 'is_integer' in f.meta: | |
data_manipulation_func = lambda src,dest: "if ("+src+" !== null && (typeof("+dest+") === 'undefined' || "+dest+" === null)) { "+dest + " = parseInt(" + src + "); }" | |
elif 'field_is_delegate_serializer' in f.meta: | |
data_manipulation_func = lambda src,dest: "if ( " + src + ') {child_post_resolve_promises.push('+ inst_type + '.post_restore(' + src + ', '+dest+').then(function(sub_result) { ' + dest + '= sub_result;})); }' | |
elif t == 'Date': | |
data_manipulation_func = lambda src,dest: 'if ('+src+" && (typeof("+dest+") === 'undefined' || "+dest+" === null)) { "+dest + ' = new Date('+src+'); }' | |
elif t == 'number': | |
data_manipulation_func = lambda src,dest: "if ("+src+" !== null && (typeof("+dest+") === 'undefined' || "+dest+" === null)) { "+dest + ' = parseFloat('+src+'); }' | |
else: | |
#if 'is_url' in f.meta: | |
# def data_manipulation_func(src,dest,idx=None): | |
# dest_obj = dest +'__obj' | |
# result = [ | |
# 'if ('+src+" && (typeof("+dest+") === 'undefined' || "+dest+" === null)) {", | |
# INDENT + dest + ' = ' + src + ';', | |
# if idx is not None: | |
# result.append( INDENT*2 + dest_obj + ' = ' + dest_obj + ' || []') | |
# result.extend([ | |
# INDENT*2 + base_factory_name + ".$http.get('" + src +"')", | |
# INDENT*3 + ".success(function(data) {", | |
# INDENT*4 + dest + '__obj' + ('' if idx is None else '['+idx+']')+ ' = data', | |
# INDENT*3 + "})", | |
# INDENT + "}", | |
# '}' | |
# ]) | |
# return result | |
#else: | |
data_manipulation_func = lambda src,dest:\ | |
'if ('+src+" && (typeof("+dest+") === 'undefined' || "+dest+" === null)) { " + dest + ' = ' + src + '; }' | |
if data_manipulation_func: | |
if 'is_array' in f.meta: | |
w(indent_ggg_child + 'result.'+f.field_name + ' = ' + 'result.'+f.field_name + ' || [];') | |
w(indent_ggg_child + 'json_obj.'+f.field_name+'.forEach(function(_,i) {') | |
inst_class = f.meta['inst_type'] | |
if callable(inst_class): | |
inst_class = inst_class() | |
inst_name = 'inst_' + str(next_inst_cnt.next()) | |
w(indent_gggg_child + 'var ' + inst_name + ';') | |
w(indent_gggg_child + 'if (i < result.'+f.field_name+'.length) {') | |
w(indent_ggggg_child + inst_name + ' = result.'+f.field_name+'[i];') | |
w(indent_gggg_child + '} else {') | |
if inst_class == 'String': | |
w(indent_ggggg_child + 'result.'+f.field_name+'.push(null);') | |
else: | |
w(indent_ggggg_child + inst_name + ' = new '+inst_class+'(); // jshint ignore:line') | |
w(indent_ggggg_child + 'result.'+f.field_name+'.push('+inst_name+');') | |
w(indent_gggg_child + '}') | |
#if 'is_url' in f.meta: | |
# w(indent_gggg_child + ('\n'+indent_gggg_child).join(data_manipulation_func('json_obj.'+f.field_name,inst_name,'i'))) | |
#else: | |
if 1: | |
w(indent_gggg_child + data_manipulation_func('json_obj.'+f.field_name+'[i]','result.'+f.field_name+'[i]')) | |
w(indent_ggg_child + '});') | |
else: | |
#if 'is_url' in f.meta: | |
# w(indent_ggg_child + ('\n'+indent_ggg_child).join(data_manipulation_func('json_obj.'+f.field_name,'result.'+f.field_name))) | |
#else: | |
w(indent_ggg_child + data_manipulation_func('json_obj.'+f.field_name,'result.'+f.field_name)) | |
w(indent_ggg_child + 'if (child_post_resolve_promises.length) {') | |
w(indent_gggg_child + 'resolve(' + base_factory_name + '.$q.all(child_post_resolve_promises).then(function() { return result; }));') | |
w(indent_ggg_child + '} else {') | |
w(indent_gggg_child + 'resolve(result);') | |
w(indent_ggg_child + '}') | |
w(indent_gg_child + "});") | |
w(indent_g_child + '};') | |
w('') | |
w(indent_g_child + cls_name + '.prototype.save = gen_inst_save(\'' + cls.meta['url'] + '\', ' + cls_name + ');') | |
#w(indent_g_child + cls_name + '.prototype.save = function() {') | |
#w(indent_gg_child + 'var req_defer = ' + base_factory_name + '.$q.defer();') | |
#w(indent_gg_child + 'var self = this;') | |
#w(indent_gg_child + 'this.pre_save().then(function(saver) {') | |
#w(indent_ggg_child + "var promise;") | |
#w(indent_ggg_child + "if ('url' in saver) {") | |
#w(indent_gggg_child + 'promise = ' + base_factory_name + ".$http.put(saver.url, saver);") | |
#w(indent_ggg_child + "} else if ('id' in saver) {") | |
#w(indent_gggg_child + 'promise = ' + base_factory_name + ".$http.put(self.base_url + saver.id + '/', saver);") | |
#w(indent_ggg_child + '} else {') | |
#w(indent_gggg_child + "promise = " + base_factory_name + ".$http.post('"+cls.meta['url']+"', saver);") | |
#w(indent_ggg_child + '}') | |
#w(indent_ggg_child + '') | |
#w(indent_ggg_child + 'promise = promise.then(function(data) {') | |
#w(indent_gggg_child + 'return ' + cls_name + '.post_restore(data.data,self);') | |
#w(indent_ggg_child + '});') | |
#w(indent_ggg_child + 'promise.catch('+base_factory_name+'.log_http_error);') | |
#w(indent_ggg_child + 'req_defer.resolve(promise);') | |
#w(indent_gg_child + '});') | |
#w(indent_gg_child + 'return req_defer.promise;') | |
#w(indent_g_child + '};') | |
w('') | |
w(indent_g_child + cls_name + '.get = gen_inst_get(\'' + cls.meta['url'] + '\', ' + cls_name + ');') | |
# w(indent_g_child + cls_name + '.get = function(pk,destination) {') | |
# w(indent_gg_child + 'destination = destination || new ' + cls_name + '();') | |
# w(indent_gg_child + 'var post_restore_intercept = function(data) {') | |
# w(indent_ggg_child + 'return ' + cls_name + '.post_restore(data.data,destination);') | |
# w(indent_gg_child + '};') | |
# w(indent_gg_child + "var url = /^\w+$/.test(pk) ? '"+cls.meta['url'] + "'+pk+'/' : pk;") | |
# w(indent_gg_child + 'var promise = '+base_factory_name+".$http.get(url)") | |
# w(indent_ggg_child+ '.then(post_restore_intercept);') | |
# w(indent_gg_child + 'promise.catch('+base_factory_name+'.log_http_error);') | |
# w(indent_gg_child + 'return promise;') | |
# w(indent_g_child + '};') | |
w('') | |
w(indent_g_child + cls_name + '.prototype.delete = gen_inst_delete(\'' + cls.meta['url'] + '\', ' + cls_name + ');') | |
# w(indent_g_child + cls_name + '.prototype.delete = function() {') | |
# w(indent_gg_child + 'if (this.url) {') | |
# w(indent_ggg_child + 'return '+base_factory_name+'.$http.delete(this.url);') | |
# w(indent_gg_child + '} else if (this.id) {') | |
# w(indent_ggg_child + "return "+base_factory_name+".$http.delete(this.base_url + this.id + '/');") | |
# w(indent_gg_child + '} else {') | |
# w(indent_ggg_child + 'return '+base_factory_name+'.$q.when(null);') | |
# w(indent_gg_child + '}') | |
# w(indent_g_child + '};') | |
w('') | |
w(indent_g_child +'return ' + cls_name + ';') | |
w(indent_child + '})();') | |
w('') | |
else: | |
child_scope = module_names + [mod_class_name] | |
child_ref = '.'.join(child_scope[-2:]) | |
w(indent_child + child_ref + '= {};') | |
w(indent_child + '(function ('+mod_class_name+') {') | |
OutputClasses(mod_class,module_names + [mod_class_name],indent_child) | |
w(indent_child + '})('+child_ref+');') | |
OutputClasses(base_module,[base_factory_name]) | |
w('})('+base_factory_name+');') | |
w('') | |
w("angular.module('app').factory('"+base_factory_name+"',[") | |
w(" '$http', 'log_http_error', '$q',") | |
w(INDENT + 'function($http, log_http_error, $q) {') | |
def export_classes(module,print_func): | |
for mod_class_name,mod_class in module.iteritems(): | |
if isinstance(mod_class,ClassDefn): | |
print_func(base_factory_name + '.' + '.'.join(mod_class.url_name)) | |
else: | |
export_classes(mod_class,print_func) | |
w(INDENT*2 + base_factory_name + '.$http = $http;') | |
w(INDENT*2 + base_factory_name + '.log_http_error = log_http_error;') | |
w(INDENT*2 + base_factory_name + '.$q = $q;') | |
w(INDENT*2 + 'return ' + base_factory_name + ';') | |
w(INDENT + '}') | |
w(']);') | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment