Procházet zdrojové kódy

added docfield utility

version-14
Rushabh Mehta před 13 roky
rodič
revize
4ef06e8bf0
9 změnil soubory, kde provedl 308 přidání a 167 odebrání
  1. binární
      css/fonts/cabin.woff
  2. +69
    -0
      py/webnotes/model/docfield.py
  3. +13
    -1
      py/webnotes/model/doclist.py
  4. +0
    -36
      py/webnotes/model/events.py
  5. +0
    -48
      py/webnotes/model/modules.py
  6. +0
    -80
      py/webnotes/model/sql_sync.py
  7. +29
    -0
      py/webnotes/tests/test_docfield.py
  8. +1
    -2
      py/webnotes/utils/__init__.py
  9. +196
    -0
      py/webnotes/utils/editdoctype.py

binární
css/fonts/cabin.woff Zobrazit soubor


+ 69
- 0
py/webnotes/model/docfield.py Zobrazit soubor

@@ -0,0 +1,69 @@
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
#
# MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

"""docfield utililtes"""

import webnotes

def rename(doctype, fieldname, newname):
"""rename docfield"""
df = webnotes.conn.sql("""select * from tabDocField where parent=%s and fieldname=%s""",
(doctype, fieldname), as_dict=1)
if not df:
return
df = df[0]
if webnotes.conn.get_value('DocType', doctype, 'issingle'):
update_single(df, newname)
else:
update_table(df, newname)
update_parent_field(df, newname)

def update_single(f, new):
"""update in tabSingles"""
webnotes.conn.begin()
webnotes.conn.sql("""update tabSingles set field=%s where doctype=%s and field=%s""",
(new, f['parent'], f['fieldname']))
webnotes.conn.commit()

def update_table(f, new):
"""update table"""
query = get_change_column_query(f, new)
if query:
webnotes.conn.sql(query)
def update_parent_field(f, new):
"""update 'parentfield' in tables"""
if f['fieldtype']=='Table':
webnotes.conn.begin()
webnotes.conn.sql("""update `tab%s` set parentfield=%s where parentfield=%s""" \
% (f['options'], '%s', '%s'), (new, f['fieldname']))
webnotes.conn.commit()
def get_change_column_query(f, new):
"""generate change fieldname query"""
desc = webnotes.conn.sql("desc `tab%s`" % f['parent'])
for d in desc:
if d[0]== f['fieldname']:
return 'alter table `tab%s` change `%s` `%s` %s' % \
(f['parent'], f['fieldname'], new, d[1])

+ 13
- 1
py/webnotes/model/doclist.py Zobrazit soubor

@@ -198,7 +198,6 @@ class DocList:
if hasattr(self.obj, 'custom_' + method): if hasattr(self.obj, 'custom_' + method):
getattr(self.obj, 'custom_' + method)() getattr(self.obj, 'custom_' + method)()


from webnotes.model.events import trigger
trigger(method, self.doc) trigger(method, self.doc)


def save_main(self): def save_main(self):
@@ -313,6 +312,19 @@ def clone(source_doclist):
return doclistobj return doclistobj




def trigger(method, doc):
"""trigger doctype events"""
try:
import startup.event_handlers
except ImportError:
return
if hasattr(startup.event_handlers, method):
getattr(startup.event_handlers, method)(doc)
if hasattr(startup.event_handlers, 'doclist_all'):
startup.event_handlers.doclist_all(doc, method)

# for bc # for bc
def getlist(doclist, parentfield): def getlist(doclist, parentfield):
""" """


+ 0
- 36
py/webnotes/model/events.py Zobrazit soubor

@@ -1,36 +0,0 @@
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
#
# MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

"""trigger doctype events"""

def trigger(method, doc):
try:
import startup.event_handlers
except ImportError:
return
if hasattr(startup.event_handlers, method):
getattr(startup.event_handlers, method)(doc)
if hasattr(startup.event_handlers, 'doclist_all'):
startup.event_handlers.doclist_all(doc, method)

+ 0
- 48
py/webnotes/model/modules.py Zobrazit soubor

@@ -1,48 +0,0 @@
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
#
# MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

# Modules
# -----------

def get_module_items(mod, only_dt=0):
dl = []
if only_dt:
transfer_types = ['DocType']
else:
transfer_types = ['Role', 'Page', 'DocType', 'DocType Mapper', 'Search Criteria']
dl = ['Module Def,'+mod]
for dt in transfer_types:
try:
dl2 = sql('select name from `tab%s` where module="%s"' % (dt,mod))
dl += [(dt+','+e[0]) for e in dl2]
except:
pass

if not only_dt:
dl1 = sql('select doctype_list from `tabModule Def` where name=%s', mod)
dl += dl1[0][0].split('\n')
# build finally
dl = [e.split(',') for e in dl]
dl = [[e[0].strip(), e[1].strip()] for e in dl] # remove blanks
return dl

+ 0
- 80
py/webnotes/model/sql_sync.py Zobrazit soubor

@@ -1,80 +0,0 @@
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
#
# MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

"""
Sync sql files (that contain triggers, stored procs etc) into the database
calling sync will walk through all .sql files in the modules file structure
and execute them if they are not executed or their timestamps have changed

All sql timestamps will be saved in a table '__sql_timestamps'
"""

# modules path
import webnotes
import webnotes.defs

def get_sql_files():
"""
Returns list of .sql files from
"""
import os
ret = []
for walk_tuple in os.walk(webnotes.defs.modules_path):
if os.path.split(walk_tuple[0])[-1]=='doctype':
for sql_file in filter(lambda x: x.endswith('.sql'), walk_tuple[2]):
ret.append[os.path.join(walk_tuple[0], sql_file)]
return ret
def run_sql_file(fn):
"""
Checks if timestamp matches, if not runs it
"""
from webnotes.modules import ModuleFile
mf = ModuleFile(fn)
if mf.is_new():
webnotes.conn.sql(mf.read())
mf.update()
def get_sql_timestamp(fn):
"""
Returns the last updated timestamp of the sql file
from the __sql_timestamps table. If the table does not
exist, it will create it
"""
try:
ts = webnotes.conn.sql("select tstamp from __sql_timestamp where file_name=%s", fn)
if ts:
return ts[0][0]
except Exception, e:
if e.args[0]==1147:
# create the table
webnotes.conn.commit()
webnotes.conn.sql("""
create table __sql_timestamp (
file_name varchar(320) primary key,
tstamp varchar(40))""")
webnotes.conn.begin()
else:
raise e
def update_sql_timestamp(fn, ts):
pass

+ 29
- 0
py/webnotes/tests/test_docfield.py Zobrazit soubor

@@ -0,0 +1,29 @@
import unittest, sys

sys.path.append('lib/py')

import webnotes
from webnotes.model import docfield
webnotes.connect()

class TestDocField(unittest.TestCase):
def test_rename(self):
docfield.rename('Event', 'notes', 'notes1')
# check in table
tf = webnotes.conn.sql("""desc tabEvent""")
self.assertTrue('notes' not in [d[0] for d in tf])
self.assertTrue('notes1' in [d[0] for d in tf])

docfield.rename('Event', 'notes1', 'notes')
def test_table_rename(self):
docfield.rename('Event', 'event_individuals', 'event_users')

self.assertFalse(webnotes.conn.sql("""select parent from `tabEvent User` where parentfield='event_individuals'"""))
self.assertTrue(webnotes.conn.sql("""select parent from `tabEvent User` where parentfield='event_users'"""))

if __name__=='__main__':
unittest.main()

+ 1
- 2
py/webnotes/utils/__init__.py Zobrazit soubor

@@ -438,8 +438,7 @@ def in_words(integer):
Returns string in words for the given integer. Returns string in words for the given integer.
""" """


in_million = webnotes.conn.get_value('Control Panel',None,'currency_format')=='Millions' and 1 or 0
in_million = webnotes.conn.get_default('currency_format')=='Millions' and 1 or 0


n=int(integer) n=int(integer)
known = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', known = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',


+ 196
- 0
py/webnotes/utils/editdoctype.py Zobrazit soubor

@@ -0,0 +1,196 @@
#!/usr/bin/python

"""
Utilty to review DocType fields:

- Will prompt each field and allow to change properties and fieldnames
- Run from command line of project home
- set fieldname_patch_file in defs.py

# todo

- update db
- parent field for table fields
"""

import os, sys

curpath = os.path.dirname(__file__)

sys.path.append(os.path.join(curpath, '..', '..'))

import webnotes
import webnotes.defs
from webnotes.modules.export_module import export_to_files
from termcolor import colored

sys.path.append(webnotes.defs.modules_path)

def update_field_property(f, property):
import webnotes

new = raw_input('New %s: ' % property)
if new:
webnotes.conn.begin()
webnotes.conn.set_value('DocField', f['name'], property, new)
webnotes.conn.commit()
export_to_files(record_list=[['DocType', f['parent']]])
return new

def remove_field(f):
webnotes.conn.begin()
webnotes.conn.sql("""delete from tabDocField where name=%s""", f['name'])
webnotes.conn.commit()
export_to_files(record_list=[['DocType', f['parent']]])

def replace_code(old, new):
"""find files with fieldname using grep and pass fieldnames to replace code"""
import subprocess

# js
proc = subprocess.Popen(['grep', '-rl', '--include=*.js', old, '.'],
shell=False, stdout = subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
for fpath in stdout.split():
ret = search_replace_with_prompt(fpath, old, new)
if ret == 'quit':
break

# py
proc = subprocess.Popen(['grep', '-rl', '--include=*.py', old, '.'],
shell=False, stdout = subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
for fpath in stdout.split():
ret = search_replace_with_prompt(fpath, old, new)
if ret == 'quit':
break

def update_fieldname_patch_file(fdata):
"""update patch file with list"""
with open(webnotes.defs.fieldname_patch_file, 'a') as patchfile:
patchfile.write(str(fdata) + '\n')

def search_replace_with_prompt(fpath, txt1, txt2):
""" Search and replace all txt1 by txt2 in the file with confirmation"""

from termcolor import colored
with open(fpath, 'r') as f:
content = f.readlines()

tmp = []
for c in content:
if c.find(txt1) != -1:
print '\n', fpath
print colored(txt1, 'red').join(c[:-1].split(txt1))
a = ''
while a not in ['y', 'n', 'Y', 'N', 's', 'q']:
a = raw_input('Do you want to Change [y/n/s/q]?')
if a.lower() == 'y':
c = c.replace(txt1, txt2)
if a.lower() == 's':
return
if a.lower() == 'q':
return 'quit'
tmp.append(c)

with open(fpath, 'w') as f:
f.write(''.join(tmp))
print colored('Updated', 'green')

def review():
"""review fields"""
start = 0
flist = webnotes.conn.sql("""select t1.name, t1.parent, t1.fieldtype, t1.label, t1.fieldname,
t1.options, t1.description from tabDocField t1, tabDocType t2 where
t1.fieldtype not in ('Section Break', 'Column Break') and
t1.fieldname not in ('address_display', 'contact_display') and
t1.parent = t2.name and
t2.module != 'Core' and
replace(replace(replace(replace(lower(label), ' ', '_'), '-', '_'), ')', ''), '(', '') != fieldname
order by parent, label""", as_dict=1)
for f in flist[start:]:
os.system('clear')
print f['parent']
print 'Fieldname: ' + colored(f['fieldname'], 'red')
print 'Label:' + f['label']
print 'Description: ' + str(f['description'])
print 'Type: ' + str(f['fieldtype'])
print 'Options: ' + str(f['options'])
print str(start) + '/' + str(len(flist))

action = ''
while action != 'n':
print '-----------------'
action = raw_input("""[n]ext, [f]ieldname, [l]abel, [d]escription, [r]emove, view [c]ode, [q]uit:""")
if action=='l':
old = f['label']
new = update_field_property(f, 'label')

# replace code for search criteria
replace_code(old, new)

elif action=='d':
update_field_property(f, 'description')
elif action=='c':
print colored('js:', 'green')
os.system('grep -r --color --include=*.js "%s" ./' % f['fieldname'])
print colored('py:', 'green')
os.system('grep -r --color --include=*.py "%s" ./' % f['fieldname'])
elif action=='f':
old = f['fieldname']
new = update_field_property(f, 'fieldname')
if new:
# rename in table and parentfield
from webnotes.model import docfield
docfield.rename(f['parent'], f['fieldname'], new)
# replace code
replace_code(old, new)
# write in fieldname patch file
update_fieldname_patch_file([f['parent'], f['fieldname'], new])
elif action=='r':
remove_field(f)
action = 'n'
elif action=='q':
return
start += 1

def setup_options():
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-a", "--all",
action="store_true", default=False,
help="Review all fields")

parser.add_option("-d", "--doctype",
nargs=1, default=False, metavar='DOCTYPE',
help="Review fields of a doctype")

parser.add_option("-f", "--field",
nargs=2, default=False, metavar='DOCTYPE FIELD',
help="Review a particular field")
return parser.parse_args()


if __name__=='__main__':
webnotes.connect()
options, args = setup_options()
if options.all:
review()
if options.doctype:
review(options.doctype)
if options.field:
review(options.field[0], options.field[1])

Načítá se…
Zrušit
Uložit