mirror of https://github.com/interlegis/sapl.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
8.8 KiB
283 lines
8.8 KiB
import os
|
|
import pprint
|
|
import re
|
|
import string
|
|
|
|
import pkg_resources
|
|
import yaml
|
|
from bs4 import BeautifulSoup
|
|
from bs4.element import NavigableString, Tag
|
|
from django.apps.config import AppConfig
|
|
|
|
from crispy_layout_mixin import heads_and_tails
|
|
from legacy.migration import appconfs, get_renames
|
|
from legacy.scripts.utils import getsourcelines
|
|
from sapl.utils import listify
|
|
|
|
# to prevent removal by automatic organize imports on this file
|
|
assert appconfs
|
|
|
|
field_renames, model_renames = get_renames()
|
|
|
|
|
|
def _read_line(tr):
|
|
for td in tr.find_all('td'):
|
|
label = td.text.strip().split('\n')[0].strip(
|
|
'\xa0' + string.whitespace)
|
|
if label.endswith('(*)'):
|
|
label = label[:-3].strip()
|
|
names = [c.attrs['name']
|
|
for c in td.findAll()
|
|
if isinstance(c, Tag) and 'name' in c.attrs]
|
|
if names:
|
|
name = names[0].split('_', 1)[-1]
|
|
yield name, label
|
|
|
|
|
|
def extract_title_and_fieldsets(model):
|
|
filename = os.path.join(os.path.dirname(__file__),
|
|
'original_forms/%s.html' % model.__name__)
|
|
try:
|
|
with open(filename, 'r') as file:
|
|
html_doc = file.read()
|
|
except IOError:
|
|
return None, []
|
|
|
|
soup = BeautifulSoup(html_doc, 'html.parser')
|
|
forms = soup.find_all('form')
|
|
[form] = [f for f in forms if ('method', 'post') in f.attrs.items()]
|
|
# children are either tags or strings...
|
|
assert set(type(c) for c in form.children) == {Tag, NavigableString}
|
|
# ... and all strings are empty
|
|
assert all(not c.strip()
|
|
for c in form.children if isinstance(c, NavigableString))
|
|
|
|
title = soup.find('h1', {'class': 'firstHeading'})
|
|
title = title.text.strip() if title else None
|
|
fieldsets = [dict(
|
|
legend=fieldset.find('legend').text if fieldset.find('legend') else '',
|
|
lines=[list(_read_line(tr)) for tr in fieldset.find_all('tr')])
|
|
for fieldset in form.find_all('fieldset')]
|
|
|
|
return title, fieldsets
|
|
|
|
|
|
def get_names_labels(fieldsets):
|
|
for fieldset in fieldsets:
|
|
for line in fieldset['lines']:
|
|
for name, label in line:
|
|
yield name, label
|
|
|
|
|
|
def print_title_and_fieldsets(model):
|
|
title, fieldsets = extract_title_and_fieldsets(model)
|
|
print('#### %s ####\n' % title)
|
|
for fieldset in fieldsets:
|
|
print(fieldset['legend'])
|
|
for line in fieldset['lines']:
|
|
print(' ' + ' | '.join('%s : %s' % (id, label)
|
|
for id, label in line))
|
|
|
|
|
|
def extract_verbose_names(model):
|
|
title, fieldsets = extract_title_and_fieldsets(model)
|
|
names_to_labels = dict(get_names_labels(fieldsets))
|
|
|
|
field_names = [f.name for f in model._meta.fields if f.name != 'id']
|
|
|
|
labels = {}
|
|
field_names_to_old = field_renames[model]
|
|
for name in field_names:
|
|
old_name = field_names_to_old[name]
|
|
label = names_to_labels.get(old_name, None)
|
|
if label:
|
|
labels[name] = label
|
|
del names_to_labels[old_name]
|
|
for name, label in labels.items():
|
|
field_names.remove(name)
|
|
non_matched = field_names, names_to_labels
|
|
return title, labels, non_matched
|
|
|
|
|
|
@listify
|
|
def source_with_verbose_names(model):
|
|
source = getsourcelines(model)
|
|
title, labels, non_matched = extract_verbose_names(model)
|
|
|
|
field_regex = ' *(.+) = (models\.[^\(]*)\((.*verbose_name=_\(.*\)|.*)\)'
|
|
new_lines = []
|
|
class_meta_already_exists = False
|
|
for line in source[1:]:
|
|
for regex, split in [
|
|
(field_regex + ' *# (.+)', lambda groups: groups),
|
|
(field_regex, lambda groups: groups + ('',))]:
|
|
match = re.match(regex, line)
|
|
if match:
|
|
name, path, args, legacy_name = split(match.groups())
|
|
if name in labels and 'verbose_name' not in args:
|
|
args = [args] if args.strip() else []
|
|
args.append("verbose_name=_('%s')" % labels[name])
|
|
args = ', '.join(args)
|
|
new_lines.append(
|
|
(' %s = %s(%s)' % (name, path, args), legacy_name))
|
|
break
|
|
else:
|
|
if 'class Meta:' in line:
|
|
class_meta_already_exists = True
|
|
new_lines.append((line, ''))
|
|
yield source[0].rstrip()
|
|
cols = max(map(len, [line for line, _ in new_lines]))
|
|
for line, legacy_name in new_lines:
|
|
line = line.rstrip().ljust(cols)
|
|
if legacy_name:
|
|
yield line + ' # ' + legacy_name
|
|
else:
|
|
yield line
|
|
|
|
# class Meta
|
|
if class_meta_already_exists:
|
|
return
|
|
|
|
if title == 'Tabelas Auxiliares':
|
|
title = ''
|
|
title = title if title else ''
|
|
|
|
def add_s(name):
|
|
return ' '.join(
|
|
p if p.endswith('s') else p + 's' for p in name.split())
|
|
|
|
def remove_s(name):
|
|
return ' '.join(p[:-1] if p.endswith('s') else p for p in name.split())
|
|
|
|
if not title:
|
|
# default title from model name
|
|
title_singular = ' '.join(re.findall('[A-Z][^A-Z]*', model.__name__))
|
|
title_singular = re.sub('cao\\b', 'ção', title_singular)
|
|
title_singular = re.sub('ao\\b', 'ão', title_singular)
|
|
title_plural = add_s(
|
|
title_singular.replace('ção', 'ções').replace('ão', 'ões'))
|
|
|
|
elif title.endswith('s'):
|
|
title_singular = remove_s(
|
|
title.replace('ções', 'ção').replace('ões', 'ão'))
|
|
title_plural = title
|
|
else:
|
|
title_singular = title
|
|
title_plural = add_s(title.replace('ção', 'ções').replace('ão', 'ões'))
|
|
|
|
yield """
|
|
class Meta:
|
|
verbose_name = _('%s')
|
|
verbose_name_plural = _('%s')""" % (title_singular, title_plural)
|
|
|
|
|
|
def print_app_with_verbose_names(app):
|
|
print('##################################################################')
|
|
header = '# -*- coding: utf-8 -*-\n'
|
|
for line in getsourcelines(app.models_module):
|
|
if line in ['# -*- coding: utf-8 -*-',
|
|
'from django.utils.translation import ugettext as _', ]:
|
|
continue
|
|
elif line == 'from django.db import models':
|
|
header += '''from django.db import models
|
|
from django.utils.translation import ugettext_lazy as _
|
|
'''
|
|
elif 'class' in line:
|
|
break
|
|
else:
|
|
header += line + '\n'
|
|
print(header.strip())
|
|
for model in app.models.values():
|
|
print('\n')
|
|
for p in source_with_verbose_names(model):
|
|
print(p)
|
|
|
|
|
|
def list_models_with_no_scrapped_data(app):
|
|
for model in app.models.values():
|
|
if not any(extract_verbose_names(model)[:2]):
|
|
print(model.__name__)
|
|
|
|
|
|
@listify
|
|
def colsplit(names):
|
|
n = len(names)
|
|
d, r = 12 // n, 12 % n
|
|
spans = [d + 1] * r + [d] * (n - r)
|
|
return zip(names, spans)
|
|
|
|
|
|
def model_name_as_snake(model):
|
|
return re.sub('([A-Z]+)', r'_\1', model.__name__).lower().strip('_')
|
|
|
|
|
|
old_names_adjustments = yaml.load(pkg_resources.resource_string(
|
|
__name__, 'old_names_adjustments.yaml'))
|
|
|
|
|
|
@listify
|
|
def extract_fieldsets_for_current(model):
|
|
__, fieldsets = extract_title_and_fieldsets(model)
|
|
if not fieldsets:
|
|
return
|
|
|
|
try:
|
|
reverse_field_renames = {v: k for k, v in field_renames[model].items()}
|
|
adjustments = old_names_adjustments.get(model.__name__)
|
|
if adjustments:
|
|
reverse_field_renames.update(adjustments)
|
|
|
|
for fieldset in fieldsets:
|
|
rows = [
|
|
colsplit(
|
|
[reverse_field_renames.get(name, '%s_FIXME' % name)
|
|
for name, ___ in line])
|
|
for line in fieldset['lines'] if line
|
|
]
|
|
yield [fieldset['legend']] + rows
|
|
except Exception as e:
|
|
print_title_and_fieldsets(model)
|
|
raise Exception(e, model)
|
|
|
|
|
|
class Under(object):
|
|
|
|
def __init__(self, arg):
|
|
self.arg = arg
|
|
|
|
def __repr__(self):
|
|
return "_('%s')" % self.arg
|
|
|
|
|
|
GAP = 12
|
|
pretty_printer = pprint.PrettyPrinter(width=80 - GAP)
|
|
|
|
|
|
def print_crispy_form(model_or_app):
|
|
if isinstance(model_or_app, AppConfig):
|
|
for model in model_or_app.models.values():
|
|
print_crispy_form(model)
|
|
else:
|
|
model = model_or_app
|
|
|
|
fieldsets = extract_fieldsets_for_current(model)
|
|
if fieldsets:
|
|
print("""
|
|
class %(name)sForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
model = %(name)s
|
|
exclude = []
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(%(name)sForm, self).__init__(*args, **kwargs)
|
|
self.helper = FormHelper()
|
|
self.helper.layout = SaplFormLayout(
|
|
""" % {'name': model.__name__})
|
|
|
|
for legend, rows in heads_and_tails(fieldsets):
|
|
lines = pretty_printer.pformat([Under(legend)] + rows) + ',\n\n'
|
|
for line in lines.splitlines():
|
|
print(' ' * GAP + line if line.strip() else '')
|
|
|
|
print(" )")
|
|
|