forked from 0x2620/pandora
include copy of django_extension, dont install django from git
This commit is contained in:
parent
055018f12e
commit
3f7215035a
200 changed files with 14119 additions and 4 deletions
215
contrib/django_extensions/django_extensions/utils/dia2django.py
Executable file
215
contrib/django_extensions/django_extensions/utils/dia2django.py
Executable file
|
|
@ -0,0 +1,215 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
##Author Igor Támara igor@tamarapatino.org
|
||||
##Use this little program as you wish, if you
|
||||
#include it in your work, let others know you
|
||||
#are using it preserving this note, you have
|
||||
#the right to make derivative works, Use it
|
||||
#at your own risk.
|
||||
#Tested to work on(etch testing 13-08-2007):
|
||||
# Python 2.4.4 (#2, Jul 17 2007, 11:56:54)
|
||||
# [GCC 4.1.3 20070629 (prerelease) (Debian 4.1.2-13)] on linux2
|
||||
|
||||
dependclasses = ["User", "Group", "Permission", "Message"]
|
||||
|
||||
import codecs
|
||||
import sys
|
||||
import gzip
|
||||
from xml.dom.minidom import * # NOQA
|
||||
import re
|
||||
import six
|
||||
|
||||
#Type dictionary translation types SQL -> Django
|
||||
tsd = {
|
||||
"text": "TextField",
|
||||
"date": "DateField",
|
||||
"varchar": "CharField",
|
||||
"int": "IntegerField",
|
||||
"float": "FloatField",
|
||||
"serial": "AutoField",
|
||||
"boolean": "BooleanField",
|
||||
"numeric": "FloatField",
|
||||
"timestamp": "DateTimeField",
|
||||
"bigint": "IntegerField",
|
||||
"datetime": "DateTimeField",
|
||||
"date": "DateField",
|
||||
"time": "TimeField",
|
||||
"bool": "BooleanField",
|
||||
"int": "IntegerField",
|
||||
}
|
||||
|
||||
#convert varchar -> CharField
|
||||
v2c = re.compile('varchar\((\d+)\)')
|
||||
|
||||
|
||||
def index(fks, id):
|
||||
"""Looks for the id on fks, fks is an array of arrays, each array has on [1]
|
||||
the id of the class in a dia diagram. When not present returns None, else
|
||||
it returns the position of the class with id on fks"""
|
||||
for i, j in fks.items():
|
||||
if fks[i][1] == id:
|
||||
return i
|
||||
return None
|
||||
|
||||
|
||||
def addparentstofks(rels, fks):
|
||||
"""Gets a list of relations, between parents and sons and a dict of
|
||||
clases named in dia, and modifies the fks to add the parent as fk to get
|
||||
order on the output of classes and replaces the base class of the son, to
|
||||
put the class parent name.
|
||||
"""
|
||||
for j in rels:
|
||||
son = index(fks, j[1])
|
||||
parent = index(fks, j[0])
|
||||
fks[son][2] = fks[son][2].replace("models.Model", parent)
|
||||
if parent not in fks[son][0]:
|
||||
fks[son][0].append(parent)
|
||||
|
||||
|
||||
def dia2django(archivo):
|
||||
models_txt = ''
|
||||
f = codecs.open(archivo, "rb")
|
||||
#dia files are gzipped
|
||||
data = gzip.GzipFile(fileobj=f).read()
|
||||
ppal = parseString(data)
|
||||
#diagram -> layer -> object -> UML - Class -> name, (attribs : composite -> name,type)
|
||||
datos = ppal.getElementsByTagName("dia:diagram")[0].getElementsByTagName("dia:layer")[0].getElementsByTagName("dia:object")
|
||||
clases = {}
|
||||
herit = []
|
||||
imports = six.u("")
|
||||
for i in datos:
|
||||
#Look for the classes
|
||||
if i.getAttribute("type") == "UML - Class":
|
||||
myid = i.getAttribute("id")
|
||||
for j in i.childNodes:
|
||||
if j.nodeType == Node.ELEMENT_NODE and j.hasAttributes():
|
||||
if j.getAttribute("name") == "name":
|
||||
actclas = j.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1]
|
||||
myname = "\nclass %s(models.Model) :\n" % actclas
|
||||
clases[actclas] = [[], myid, myname, 0]
|
||||
if j.getAttribute("name") == "attributes":
|
||||
for l in j.getElementsByTagName("dia:composite"):
|
||||
if l.getAttribute("type") == "umlattribute":
|
||||
#Look for the attribute name and type
|
||||
for k in l.getElementsByTagName("dia:attribute"):
|
||||
if k.getAttribute("name") == "name":
|
||||
nc = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1]
|
||||
elif k.getAttribute("name") == "type":
|
||||
tc = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1]
|
||||
elif k.getAttribute("name") == "value":
|
||||
val = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1]
|
||||
if val == '##':
|
||||
val = ''
|
||||
elif k.getAttribute("name") == "visibility" and k.getElementsByTagName("dia:enum")[0].getAttribute("val") == "2":
|
||||
if tc.replace(" ", "").lower().startswith("manytomanyfield("):
|
||||
#If we find a class not in our model that is marked as being to another model
|
||||
newc = tc.replace(" ", "")[16:-1]
|
||||
if dependclasses.count(newc) == 0:
|
||||
dependclasses.append(newc)
|
||||
if tc.replace(" ", "").lower().startswith("foreignkey("):
|
||||
#If we find a class not in our model that is marked as being to another model
|
||||
newc = tc.replace(" ", "")[11:-1]
|
||||
if dependclasses.count(newc) == 0:
|
||||
dependclasses.append(newc)
|
||||
|
||||
#Mapping SQL types to Django
|
||||
varch = v2c.search(tc)
|
||||
if tc.replace(" ", "").startswith("ManyToManyField("):
|
||||
myfor = tc.replace(" ", "")[16:-1]
|
||||
if actclas == myfor:
|
||||
#In case of a recursive type, we use 'self'
|
||||
tc = tc.replace(myfor, "'self'")
|
||||
elif clases[actclas][0].count(myfor) == 0:
|
||||
#Adding related class
|
||||
if myfor not in dependclasses:
|
||||
#In case we are using Auth classes or external via protected dia visibility
|
||||
clases[actclas][0].append(myfor)
|
||||
tc = "models." + tc
|
||||
if len(val) > 0:
|
||||
tc = tc.replace(")", "," + val + ")")
|
||||
elif tc.find("Field") != -1:
|
||||
if tc.count("()") > 0 and len(val) > 0:
|
||||
tc = "models.%s" % tc.replace(")", "," + val + ")")
|
||||
else:
|
||||
tc = "models.%s(%s)" % (tc, val)
|
||||
elif tc.replace(" ", "").startswith("ForeignKey("):
|
||||
myfor = tc.replace(" ", "")[11:-1]
|
||||
if actclas == myfor:
|
||||
#In case of a recursive type, we use 'self'
|
||||
tc = tc.replace(myfor, "'self'")
|
||||
elif clases[actclas][0].count(myfor) == 0:
|
||||
#Adding foreign classes
|
||||
if myfor not in dependclasses:
|
||||
#In case we are using Auth classes
|
||||
clases[actclas][0].append(myfor)
|
||||
tc = "models." + tc
|
||||
if len(val) > 0:
|
||||
tc = tc.replace(")", "," + val + ")")
|
||||
elif varch is None:
|
||||
tc = "models." + tsd[tc.strip().lower()] + "(" + val + ")"
|
||||
else:
|
||||
tc = "models.CharField(max_length=" + varch.group(1) + ")"
|
||||
if len(val) > 0:
|
||||
tc = tc.replace(")", ", " + val + " )")
|
||||
if not (nc == "id" and tc == "AutoField()"):
|
||||
clases[actclas][2] = clases[actclas][2] + (" %s = %s\n" % (nc, tc))
|
||||
elif i.getAttribute("type") == "UML - Generalization":
|
||||
mycons = ['A', 'A']
|
||||
a = i.getElementsByTagName("dia:connection")
|
||||
for j in a:
|
||||
if len(j.getAttribute("to")):
|
||||
mycons[int(j.getAttribute("handle"))] = j.getAttribute("to")
|
||||
print(mycons)
|
||||
if not 'A' in mycons:
|
||||
herit.append(mycons)
|
||||
elif i.getAttribute("type") == "UML - SmallPackage":
|
||||
a = i.getElementsByTagName("dia:string")
|
||||
for j in a:
|
||||
if len(j.childNodes[0].data[1:-1]):
|
||||
imports += six.u("from %s.models import *" % j.childNodes[0].data[1:-1])
|
||||
|
||||
addparentstofks(herit, clases)
|
||||
#Ordering the appearance of classes
|
||||
#First we make a list of the classes each classs is related to.
|
||||
ordered = []
|
||||
for j, k in clases.iteritems():
|
||||
k[2] = k[2] + "\n def __unicode__(self):\n return u\"\"\n"
|
||||
for fk in k[0]:
|
||||
if fk not in dependclasses:
|
||||
clases[fk][3] += 1
|
||||
ordered.append([j] + k)
|
||||
|
||||
i = 0
|
||||
while i < len(ordered):
|
||||
mark = i
|
||||
j = i + 1
|
||||
while j < len(ordered):
|
||||
if ordered[i][0] in ordered[j][1]:
|
||||
mark = j
|
||||
j += 1
|
||||
if mark == i:
|
||||
i += 1
|
||||
else:
|
||||
# swap %s in %s" % ( ordered[i] , ordered[mark]) to make ordered[i] to be at the end
|
||||
if ordered[i][0] in ordered[mark][1] and ordered[mark][0] in ordered[i][1]:
|
||||
#Resolving simplistic circular ForeignKeys
|
||||
print("Not able to resolve circular ForeignKeys between %s and %s" % (ordered[i][1], ordered[mark][0]))
|
||||
break
|
||||
a = ordered[i]
|
||||
ordered[i] = ordered[mark]
|
||||
ordered[mark] = a
|
||||
if i == len(ordered) - 1:
|
||||
break
|
||||
ordered.reverse()
|
||||
if imports:
|
||||
models_txt = str(imports)
|
||||
for i in ordered:
|
||||
models_txt += '%s\n' % str(i[3])
|
||||
|
||||
return models_txt
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
dia2django(sys.argv[1])
|
||||
else:
|
||||
print(" Use:\n \n " + sys.argv[0] + " diagram.dia\n\n")
|
||||
23
contrib/django_extensions/django_extensions/utils/text.py
Normal file
23
contrib/django_extensions/django_extensions/utils/text.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import six
|
||||
|
||||
from django.utils.functional import allow_lazy
|
||||
|
||||
# conditional import, force_unicode was renamed in Django 1.5
|
||||
try:
|
||||
from django.utils.encoding import force_unicode # NOQA
|
||||
except ImportError:
|
||||
from django.utils.encoding import force_text as force_unicode # NOQA
|
||||
|
||||
|
||||
def truncate_letters(s, num):
|
||||
"""
|
||||
truncates a string to a number of letters, similar to truncate_words
|
||||
"""
|
||||
s = force_unicode(s)
|
||||
length = int(num)
|
||||
if len(s) > length:
|
||||
s = s[:length]
|
||||
if not s.endswith('...'):
|
||||
s += '...'
|
||||
return s
|
||||
truncate_letters = allow_lazy(truncate_letters, six.text_type)
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
from django.template.base import Library, Node
|
||||
from django.template import defaulttags
|
||||
from django.templatetags import future
|
||||
register = Library()
|
||||
|
||||
error_on_old_style_url_tag = False
|
||||
new_style_url_tag = False
|
||||
errors = []
|
||||
|
||||
|
||||
def before_new_template(force_new_urls):
|
||||
"""Reset state ready for new template"""
|
||||
global new_style_url_tag, error_on_old_style_url_tag, errors
|
||||
new_style_url_tag = False
|
||||
error_on_old_style_url_tag = force_new_urls
|
||||
errors = []
|
||||
|
||||
|
||||
def get_template_errors():
|
||||
return errors
|
||||
|
||||
|
||||
# Disable extends and include as they are not needed, slow parsing down, and cause duplicate errors
|
||||
class NoOpNode(Node):
|
||||
def render(self, context):
|
||||
return ''
|
||||
|
||||
|
||||
@register.tag
|
||||
def extends(parser, token):
|
||||
return NoOpNode()
|
||||
|
||||
|
||||
@register.tag
|
||||
def include(parser, token):
|
||||
return NoOpNode()
|
||||
|
||||
|
||||
# We replace load to determine whether new style urls are in use and re-patch url after
|
||||
# a future version is loaded
|
||||
@register.tag
|
||||
def load(parser, token):
|
||||
global new_style_url_tag
|
||||
bits = token.contents.split()
|
||||
|
||||
reloaded_url_tag = False
|
||||
if len(bits) >= 4 and bits[-2] == "from" and bits[-1] == "future":
|
||||
for name in bits[1:-2]:
|
||||
if name == "url":
|
||||
new_style_url_tag = True
|
||||
reloaded_url_tag = True
|
||||
|
||||
try:
|
||||
return defaulttags.load(parser, token)
|
||||
finally:
|
||||
if reloaded_url_tag:
|
||||
parser.tags['url'] = new_style_url
|
||||
|
||||
|
||||
@register.tag(name='url')
|
||||
def old_style_url(parser, token):
|
||||
global error_on_old_style_url_tag
|
||||
|
||||
bits = token.split_contents()
|
||||
view = bits[1]
|
||||
|
||||
if error_on_old_style_url_tag:
|
||||
_error("Old style url tag used (only reported once per file): {%% %s %%}" % (" ".join(bits)), token)
|
||||
error_on_old_style_url_tag = False
|
||||
|
||||
if view[0] in "\"'" and view[0] == view[-1]:
|
||||
_error("Old style url tag with quotes around view name: {%% %s %%}" % (" ".join(bits)), token)
|
||||
|
||||
return defaulttags.url(parser, token)
|
||||
|
||||
|
||||
def new_style_url(parser, token):
|
||||
bits = token.split_contents()
|
||||
view = bits[1]
|
||||
|
||||
if view[0] not in "\"'" or view[0] != view[-1]:
|
||||
_error("New style url tag without quotes around view name: {%% %s %%}" % (" ".join(bits)), token)
|
||||
|
||||
return future.url(parser, token)
|
||||
|
||||
|
||||
def _error(message, token):
|
||||
origin, (start, upto) = token.source
|
||||
source = origin.reload()
|
||||
line = source.count("\n", 0, start) + 1 # 1 based line numbering
|
||||
errors.append((origin, line, message))
|
||||
Loading…
Add table
Add a link
Reference in a new issue