Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

852 строки
22 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. # util __init__.py
  23. from __future__ import unicode_literals
  24. import webnotes
  25. user_time_zone = None
  26. month_name = ['','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
  27. month_name_full = ['','January','February','March','April','May','June','July','August','September','October','November','December']
  28. no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'FlexTable', 'Button', 'Image', 'Graph']
  29. default_fields = ['doctype','name','owner','creation','modified','modified_by','parent','parentfield','parenttype','idx','docstatus']
  30. def getCSVelement(v):
  31. """
  32. Returns the CSV value of `v`, For example:
  33. * apple becomes "apple"
  34. * hi"there becomes "hi""there"
  35. """
  36. v = cstr(v)
  37. if not v: return ''
  38. if (',' in v) or ('\n' in v) or ('"' in v):
  39. if '"' in v: v = v.replace('"', '""')
  40. return '"'+v+'"'
  41. else: return v or ''
  42. def get_fullname(profile):
  43. """get the full name (first name + last name) of the user from Profile"""
  44. p = webnotes.conn.sql("""select first_name, last_name from `tabProfile`
  45. where name=%s""", profile, as_dict=1)
  46. if p:
  47. p = p[0]
  48. full_name = (p['first_name'] and (p['first_name'] + ' ') or '') + (p['last_name'] or '')
  49. return full_name or profile
  50. else:
  51. return profile
  52. def decode_email_header(s):
  53. import email.header
  54. # replace double quotes with blank
  55. # double quotes in header prohibit decoding of header
  56. decoded_header_tuple = email.header.decode_header(s.replace('"', ''))
  57. decoded_list = map(lambda h: unicode(h[0], encoding=h[1] or 'utf-8'), decoded_header_tuple)
  58. return " ".join(decoded_list)
  59. def extract_email_id(s):
  60. """
  61. Extract email id from email header format
  62. """
  63. if '<' in s:
  64. s = s.split('<')[1].split('>')[0]
  65. if s:
  66. s = s.strip().lower()
  67. return s
  68. def get_email_id(user):
  69. """get email id of user formatted as: John Doe <johndoe@example.com>"""
  70. if user == "Administrator":
  71. return user
  72. fullname = get_fullname(user)
  73. return "%s <%s>" % (fullname, user)
  74. def validate_email_add(email_str):
  75. """Validates the email string"""
  76. s = extract_email_id(email_str)
  77. import re
  78. #return re.match("^[a-zA-Z0-9._%-]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email_str)
  79. return re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", s)
  80. def sendmail(recipients, sender='', msg='', subject='[No Subject]', parts=[], cc=[], attach=[]):
  81. """Send an email. For more details see :func:`email_lib.sendmail`"""
  82. import webnotes.utils.email_lib
  83. return email_lib.sendmail(recipients, sender, msg, subject, parts, cc, attach)
  84. def get_request_site_address():
  85. """get app url from request"""
  86. import os
  87. try:
  88. return 'HTTPS' in os.environ.get('SERVER_PROTOCOL') and 'https://' or 'http://' \
  89. + os.environ.get('HTTP_HOST')
  90. except TypeError, e:
  91. return 'http://localhost'
  92. def random_string(length):
  93. """generate a random string"""
  94. import string
  95. from random import choice
  96. return ''.join([choice(string.letters + string.digits) for i in range(length)])
  97. def db_exists(dt, dn):
  98. return webnotes.conn.sql('select name from `tab%s` where name="%s"' % (dt, dn))
  99. def load_json(arg):
  100. # already a dictionary?
  101. if not isinstance(arg, basestring):
  102. return arg
  103. import json
  104. return json.loads(arg, encoding='utf-8')
  105. # Get Traceback
  106. # ==============================================================================
  107. def getTraceback():
  108. """
  109. Returns the traceback of the Exception
  110. """
  111. import sys, traceback, string
  112. exc_type, value, tb = sys.exc_info()
  113. trace_list = traceback.format_tb(tb, None) + traceback.format_exception_only(exc_type, value)
  114. body = "Traceback (innermost last):\n" + "%-20s %s" % \
  115. (unicode((b"").join(trace_list[:-1]), 'utf-8'), unicode(trace_list[-1], 'utf-8'))
  116. if webnotes.logger:
  117. webnotes.logger.error('Db:'+(webnotes.conn and webnotes.conn.cur_db_name or '') + ' - ' + body)
  118. return body
  119. # Log
  120. # ==============================================================================
  121. def log(event, details):
  122. webnotes.logger.info(details)
  123. # Date and Time
  124. # ==============================================================================
  125. def getdate(string_date):
  126. """
  127. Coverts string date (yyyy-mm-dd) to datetime.date object
  128. """
  129. import datetime
  130. if type(string_date)==unicode:
  131. string_date = str(string_date)
  132. if type(string_date) in (datetime.datetime, datetime.date):
  133. return string_date
  134. if ' ' in string_date:
  135. string_date = string_date.split(' ')[0]
  136. t = string_date.split('-')
  137. if len(t)==3:
  138. return datetime.date(cint(t[0]), cint(t[1]), cint(t[2]))
  139. else:
  140. return ''
  141. def add_days(date, days, format='string'):
  142. """
  143. Adds `days` to the given `string_date`
  144. """
  145. import datetime
  146. if not date:
  147. date = now_datetime()
  148. if type(date) not in (datetime.datetime, datetime.date):
  149. date = getdate(date)
  150. dt = date + datetime.timedelta(days)
  151. if format=='string':
  152. return dt.strftime('%Y-%m-%d')
  153. else:
  154. return dt
  155. def add_months(string_date, months):
  156. import datetime
  157. return webnotes.conn.sql("select DATE_ADD('%s',INTERVAL '%s' MONTH)" % (getdate(string_date),months))[0][0]
  158. def add_years(string_date, years):
  159. import datetime
  160. return webnotes.conn.sql("select DATE_ADD('%s',INTERVAL '%s' YEAR)" % (getdate(string_date),years))[0][0]
  161. def date_diff(string_ed_date, string_st_date=None):
  162. import datetime
  163. return webnotes.conn.sql("SELECT DATEDIFF('%s','%s')" %(getdate(string_ed_date), getdate(string_st_date)))[0][0]
  164. def now_datetime():
  165. global user_time_zone
  166. from datetime import datetime
  167. from pytz import timezone
  168. # get localtime
  169. if not user_time_zone:
  170. user_time_zone = webnotes.conn.get_value('Control Panel', None, 'time_zone') \
  171. or 'Asia/Calcutta'
  172. # convert to UTC
  173. utcnow = timezone('UTC').localize(datetime.utcnow())
  174. # convert to user time zone
  175. return utcnow.astimezone(timezone(user_time_zone))
  176. def now():
  177. """return current datetime as yyyy-mm-dd hh:mm:ss"""
  178. return now_datetime().strftime('%Y-%m-%d %H:%M:%S')
  179. def nowdate():
  180. """return current date as yyyy-mm-dd"""
  181. return now_datetime().strftime('%Y-%m-%d')
  182. def nowtime():
  183. """return current time in hh:mm"""
  184. return now_datetime().strftime('%H:%M')
  185. def get_first_day(dt, d_years=0, d_months=0):
  186. """
  187. Returns the first day of the month for the date specified by date object
  188. Also adds `d_years` and `d_months` if specified
  189. """
  190. import datetime
  191. # d_years, d_months are "deltas" to apply to dt
  192. y, m = dt.year + d_years, dt.month + d_months
  193. a, m = divmod(m-1, 12)
  194. return datetime.date(y+a, m+1, 1)
  195. def get_last_day(dt):
  196. """
  197. Returns last day of the month using:
  198. `get_first_day(dt, 0, 1) + datetime.timedelta(-1)`
  199. """
  200. import datetime
  201. return get_first_day(dt, 0, 1) + datetime.timedelta(-1)
  202. user_format = None
  203. """
  204. User format specified in :term:`Control Panel`
  205. Examples:
  206. * dd-mm-yyyy
  207. * mm-dd-yyyy
  208. * dd/mm/yyyy
  209. """
  210. def formatdate(string_date=None):
  211. """
  212. Convers the given string date to :data:`user_format`
  213. """
  214. global user_format
  215. if not user_format:
  216. user_format = webnotes.conn.get_value('Control Panel', None, 'date_format')
  217. if not string_date:
  218. string_date = nowdate()
  219. if not isinstance(string_date, basestring):
  220. string_date = str(string_date)
  221. d = string_date.split('-');
  222. out = user_format
  223. return out.replace('dd', ('%.2i' % cint(d[2]))).replace('mm', ('%.2i' % cint(d[1]))).replace('yyyy', d[0])
  224. def dict_to_str(args, sep='&'):
  225. """
  226. Converts a dictionary to URL
  227. """
  228. import urllib
  229. t = []
  230. for k in args.keys():
  231. t.append(str(k)+'='+urllib.quote(str(args[k] or '')))
  232. return sep.join(t)
  233. def timestamps_equal(t1, t2):
  234. """Returns true if same the two string timestamps are same"""
  235. scrub = lambda x: x.replace(':', ' ').replace('-',' ').split()
  236. t1, t2 = scrub(t1), scrub(t2)
  237. if len(t1) != len(t2):
  238. return
  239. for i in range(len(t1)):
  240. if t1[i]!=t2[i]:
  241. return
  242. return 1
  243. def global_date_format(date):
  244. """returns date as 1 January 2012"""
  245. import datetime
  246. if isinstance(date, basestring):
  247. date = getdate(date)
  248. return cstr(cint(date.strftime('%d'))) + ' ' + month_name_full[int(date.strftime('%m'))] \
  249. + ' ' + date.strftime('%Y')
  250. # Datatype
  251. # ==============================================================================
  252. def isNull(v):
  253. """
  254. Returns true if v='' or v is `None`
  255. """
  256. return (v=='' or v==None)
  257. def has_common(l1, l2):
  258. """
  259. Returns true if there are common elements in lists l1 and l2
  260. """
  261. for l in l1:
  262. if l in l2:
  263. return 1
  264. return 0
  265. def flt(s):
  266. """
  267. Convert to float (ignore commas)
  268. """
  269. if isinstance(s, basestring): # if string
  270. s = s.replace(',','')
  271. try: tmp = float(s)
  272. except: tmp = 0
  273. return tmp
  274. def cint(s):
  275. """
  276. Convert to integer
  277. """
  278. try: tmp = int(float(s))
  279. except: tmp = 0
  280. return tmp
  281. def cstr(s):
  282. if isinstance(s, unicode):
  283. return s
  284. elif s==None:
  285. return ''
  286. elif isinstance(s, basestring):
  287. return unicode(s, 'utf-8')
  288. else:
  289. return unicode(s)
  290. def str_esc_quote(s):
  291. """
  292. Escape quotes
  293. """
  294. if s==None:return ''
  295. return s.replace("'","\'")
  296. def replace_newlines(s):
  297. """
  298. Replace newlines by '<br>'
  299. """
  300. if s==None:return ''
  301. return s.replace("\n","<br>")
  302. def encode(obj, encoding="utf-8"):
  303. if isinstance(obj, list):
  304. out = []
  305. for o in obj:
  306. if isinstance(o, unicode):
  307. out.append(o.encode(encoding))
  308. else:
  309. out.append(o)
  310. return out
  311. elif isinstance(obj, unicode):
  312. return obj.encode(encoding)
  313. else:
  314. return obj
  315. # ==============================================================================
  316. def parse_val(v):
  317. """
  318. Converts to simple datatypes from SQL query results
  319. """
  320. import datetime
  321. if type(v)==datetime.date:
  322. v = str(v)
  323. elif type(v)==datetime.timedelta:
  324. v = ':'.join(str(v).split(':')[:2])
  325. elif type(v)==datetime.datetime:
  326. v = str(v)
  327. elif type(v)==long: v=int(v)
  328. return v
  329. # ==============================================================================
  330. #
  331. # def fmt_money(amount, decimal_fmt="%02.d"):
  332. # """
  333. # Convert to string with commas for thousands, millions etc
  334. # """
  335. # currency_format = webnotes.conn.get_value('Control Panel', None, 'currency_format') \
  336. # or 'Millions'
  337. # comma_frequency = (currency_format == "Millions") and 3 or 2
  338. # minus = flt(amount) < 0 and "-" or ""
  339. #
  340. # # get whole and fraction parts
  341. # str_amount = cstr(amount)
  342. # if "." in str_amount:
  343. # amount_whole = abs(cint(str_amount.split(".")[0]))
  344. # amount_fraction = cint(str_amount.split(".")[1])
  345. # else:
  346. # amount_whole = abs(cint(str_amount))
  347. # amount_fraction = 0
  348. #
  349. # # reverse the whole part, so that it is easy to append commas
  350. # whole_reversed = cstr(amount_whole)[::-1]
  351. # whole_with_comma = whole_reversed[:3]
  352. # if len(whole_reversed) > 3:
  353. # remaining_str = whole_reversed[3:]
  354. # for i in xrange(len(remaining_str)):
  355. # # insert a comma after the specified frequency of digits
  356. # if i%comma_frequency==0:
  357. # whole_with_comma += ","
  358. # whole_with_comma += remaining_str[i]
  359. # # reverse the whole part again to get the original number back!
  360. # whole_with_comma = whole_with_comma[::-1]
  361. # webnotes.msgprint(decimal_fmt)
  362. # webnotes.msgprint(("%s%s."+decimal_fmt) % (minus, whole_with_comma, amount_fraction))
  363. # return ("%s%s."+decimal_fmt) % (minus, whole_with_comma, amount_fraction)
  364. def fmt_money(amount, precision=2):
  365. """
  366. Convert to string with commas for thousands, millions etc
  367. """
  368. curr = webnotes.conn.get_value('Control Panel', None, 'currency_format') or 'Millions'
  369. amount = '%.*f' % (precision, flt(amount))
  370. val = 2
  371. if curr == 'Millions': val = 3
  372. if amount.find('.') == -1: temp = '00'
  373. else: temp = amount.split('.')[1]
  374. l = []
  375. minus = ''
  376. if flt(amount) < 0: minus = '-'
  377. amount = ''.join(amount.split(','))
  378. amount = cstr(abs(flt(amount))).split('.')[0]
  379. # main logic
  380. if len(amount) > 3:
  381. nn = amount[len(amount)-3:]
  382. l.append(nn)
  383. amount = amount[0:len(amount)-3]
  384. while len(amount) > val:
  385. nn = amount[len(amount)-val:]
  386. l.insert(0,nn)
  387. amount = amount[0:len(amount)-val]
  388. if len(amount) > 0: l.insert(0,amount)
  389. amount = ','.join(l)+'.'+temp
  390. amount = minus + amount
  391. return amount
  392. #
  393. # convet currency to words
  394. #
  395. def money_in_words(number, main_currency = None, fraction_currency=None):
  396. """
  397. Returns string in words with currency and fraction currency.
  398. """
  399. d = get_defaults()
  400. if not main_currency:
  401. main_currency = d.get('currency', 'INR')
  402. if not fraction_currency:
  403. fraction_currency = d.get('fraction_currency', 'paise')
  404. n = "%.2f" % flt(number)
  405. main, fraction = n.split('.')
  406. if len(fraction)==1: fraction += '0'
  407. out = main_currency + ' ' + in_words(main).title()
  408. if cint(fraction):
  409. out = out + ' and ' + in_words(fraction).title() + ' ' + fraction_currency
  410. return out + ' only.'
  411. #
  412. # convert number to words
  413. #
  414. def in_words(integer):
  415. """
  416. Returns string in words for the given integer.
  417. """
  418. in_million = webnotes.conn.get_default('currency_format')=='Millions' and 1 or 0
  419. n=int(integer)
  420. known = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
  421. 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen',
  422. 19: 'nineteen', 20: 'twenty', 30: 'thirty', 40: 'forty', 50: 'fifty', 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety'}
  423. def psn(n, known, xpsn):
  424. import sys;
  425. if n in known: return known[n]
  426. bestguess, remainder = str(n), 0
  427. if n<=20:
  428. print >>sys.stderr, n, "How did this happen?"
  429. assert 0
  430. elif n < 100:
  431. bestguess= xpsn((n//10)*10, known, xpsn) + '-' + xpsn(n%10, known, xpsn)
  432. return bestguess
  433. elif n < 1000:
  434. bestguess= xpsn(n//100, known, xpsn) + ' ' + 'hundred'
  435. remainder = n%100
  436. else:
  437. if in_million:
  438. if n < 1000000:
  439. bestguess= xpsn(n//1000, known, xpsn) + ' ' + 'thousand'
  440. remainder = n%1000
  441. elif n < 1000000000:
  442. bestguess= xpsn(n//1000000, known, xpsn) + ' ' + 'million'
  443. remainder = n%1000000
  444. else:
  445. bestguess= xpsn(n//1000000000, known, xpsn) + ' ' + 'billion'
  446. remainder = n%1000000000
  447. else:
  448. if n < 100000:
  449. bestguess= xpsn(n//1000, known, xpsn) + ' ' + 'thousand'
  450. remainder = n%1000
  451. elif n < 10000000:
  452. bestguess= xpsn(n//100000, known, xpsn) + ' ' + 'lakh'
  453. remainder = n%100000
  454. else:
  455. bestguess= xpsn(n//10000000, known, xpsn) + ' ' + 'crore'
  456. remainder = n%10000000
  457. if remainder:
  458. if remainder >= 100:
  459. comma = ','
  460. else:
  461. comma = ''
  462. return bestguess + comma + ' ' + xpsn(remainder, known, xpsn)
  463. else:
  464. return bestguess
  465. return psn(n, known, psn)
  466. # Get Defaults
  467. # ==============================================================================
  468. def get_defaults(key=None):
  469. """
  470. Get dictionary of default values from the :term:`Control Panel`, or a value if key is passed
  471. """
  472. return webnotes.conn.get_defaults(key)
  473. def set_default(key, val):
  474. """
  475. Set / add a default value to :term:`Control Panel`
  476. """
  477. return webnotes.conn.set_default(key, val)
  478. #
  479. # Clear recycle bin
  480. #
  481. def clear_recycle_bin():
  482. sql = webnotes.conn.sql
  483. tl = sql('show tables')
  484. total_deleted = 0
  485. for t in tl:
  486. fl = [i[0] for i in sql('desc `%s`' % t[0])]
  487. if 'name' in fl:
  488. total_deleted += sql("select count(*) from `%s` where name like '__overwritten:%%'" % t[0])[0][0]
  489. sql("delete from `%s` where name like '__overwritten:%%'" % t[0])
  490. if 'parent' in fl:
  491. total_deleted += sql("select count(*) from `%s` where parent like '__oldparent:%%'" % t[0])[0][0]
  492. sql("delete from `%s` where parent like '__oldparent:%%'" % t[0])
  493. total_deleted += sql("select count(*) from `%s` where parent like 'oldparent:%%'" % t[0])[0][0]
  494. sql("delete from `%s` where parent like 'oldparent:%%'" % t[0])
  495. total_deleted += sql("select count(*) from `%s` where parent like 'old_parent:%%'" % t[0])[0][0]
  496. sql("delete from `%s` where parent like 'old_parent:%%'" % t[0])
  497. return "%s records deleted" % str(int(total_deleted))
  498. # Dictionary utils
  499. # ==============================================================================
  500. def remove_blanks(d):
  501. """
  502. Returns d with empty ('' or None) values stripped
  503. """
  504. empty_keys = []
  505. for key in d:
  506. if d[key]=='' or d[key]==None:
  507. # del d[key] raises runtime exception, using a workaround
  508. empty_keys.append(key)
  509. for key in empty_keys:
  510. del d[key]
  511. return d
  512. def pprint_dict(d, level=1, no_blanks=True):
  513. """
  514. Pretty print a dictionary with indents
  515. """
  516. if no_blanks:
  517. remove_blanks(d)
  518. # make indent
  519. indent, ret = '', ''
  520. for i in range(0,level): indent += '\t'
  521. # add lines
  522. comment, lines = '', []
  523. kl = d.keys()
  524. kl.sort()
  525. # make lines
  526. for key in kl:
  527. if key != '##comment':
  528. tmp = {key: d[key]}
  529. lines.append(indent + str(tmp)[1:-1] )
  530. # add comment string
  531. if '##comment' in kl:
  532. ret = ('\n' + indent) + '# ' + d['##comment'] + '\n'
  533. # open
  534. ret += indent + '{\n'
  535. # lines
  536. ret += indent + ',\n\t'.join(lines)
  537. # close
  538. ret += '\n' + indent + '}'
  539. return ret
  540. def get_common(d1,d2):
  541. """
  542. returns (list of keys) the common part of two dicts
  543. """
  544. return [p for p in d1 if p in d2 and d1[p]==d2[p]]
  545. def get_common_dict(d1, d2):
  546. """
  547. return common dictionary of d1 and d2
  548. """
  549. ret = {}
  550. for key in d1:
  551. if key in d2 and d2[key]==d1[key]:
  552. ret[key] = d1[key]
  553. return ret
  554. def get_diff_dict(d1, d2):
  555. """
  556. return common dictionary of d1 and d2
  557. """
  558. diff_keys = set(d2.keys()).difference(set(d1.keys()))
  559. ret = {}
  560. for d in diff_keys: ret[d] = d2[d]
  561. return ret
  562. def get_file_timestamp(fn):
  563. """
  564. Returns timestamp of the given file
  565. """
  566. import os
  567. from webnotes.utils import cint
  568. try:
  569. return str(cint(os.stat(fn).st_mtime))
  570. except OSError, e:
  571. if e.args[0]!=2:
  572. raise e
  573. else:
  574. return None
  575. # to be deprecated
  576. def make_esc(esc_chars):
  577. """
  578. Function generator for Escaping special characters
  579. """
  580. return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
  581. # esc / unescape characters -- used for command line
  582. def esc(s, esc_chars):
  583. """
  584. Escape special characters
  585. """
  586. for c in esc_chars:
  587. esc_str = '\\' + c
  588. s = s.replace(c, esc_str)
  589. return s
  590. def unesc(s, esc_chars):
  591. """
  592. UnEscape special characters
  593. """
  594. for c in esc_chars:
  595. esc_str = '\\' + c
  596. s = s.replace(esc_str, c)
  597. return s
  598. def strip_html(text):
  599. """
  600. removes anything enclosed in and including <>
  601. """
  602. import re
  603. return re.compile(r'<.*?>').sub('', text)
  604. def escape_html(text):
  605. html_escape_table = {
  606. "&": "&amp;",
  607. '"': "&quot;",
  608. "'": "&apos;",
  609. ">": "&gt;",
  610. "<": "&lt;",
  611. }
  612. return "".join(html_escape_table.get(c,c) for c in text)
  613. def get_doctype_label(dt=None):
  614. """
  615. Gets label of a doctype
  616. """
  617. if dt:
  618. res = webnotes.conn.sql("""\
  619. SELECT name, dt_label FROM `tabDocType Label`
  620. WHERE name=%s""", dt)
  621. return res and res[0][0] or dt
  622. else:
  623. res = webnotes.conn.sql("SELECT name, dt_label FROM `tabDocType Label`")
  624. dt_label_dict = {}
  625. for r in res:
  626. dt_label_dict[r[0]] = r[1]
  627. return dt_label_dict
  628. def get_label_doctype(label):
  629. """
  630. Gets doctype from its label
  631. """
  632. res = webnotes.conn.sql("""\
  633. SELECT name FROM `tabDocType Label`
  634. WHERE dt_label=%s""", label)
  635. return res and res[0][0] or label
  636. def pretty_date(iso_datetime):
  637. """
  638. Takes an ISO time and returns a string representing how
  639. long ago the date represents.
  640. Ported from PrettyDate by John Resig
  641. """
  642. if not iso_datetime: return ''
  643. from datetime import datetime
  644. import math
  645. if isinstance(iso_datetime, basestring):
  646. iso_datetime = datetime.strptime(iso_datetime, '%Y-%m-%d %H:%M:%S')
  647. now_dt = datetime.strptime(now(), '%Y-%m-%d %H:%M:%S')
  648. dt_diff = now_dt - iso_datetime
  649. # available only in python 2.7+
  650. # dt_diff_seconds = dt_diff.total_seconds()
  651. dt_diff_seconds = dt_diff.days * 86400.0 + dt_diff.seconds
  652. dt_diff_days = math.floor(dt_diff_seconds / 86400.0)
  653. # differnt cases
  654. if dt_diff_seconds < 60.0:
  655. return 'just now'
  656. elif dt_diff_seconds < 120.0:
  657. return '1 minute ago'
  658. elif dt_diff_seconds < 3600.0:
  659. return '%s minutes ago' % cint(math.floor(dt_diff_seconds / 60.0))
  660. elif dt_diff_seconds < 7200.0:
  661. return '1 hour ago'
  662. elif dt_diff_seconds < 86400.0:
  663. return '%s hours ago' % cint(math.floor(dt_diff_seconds / 3600.0))
  664. elif dt_diff_days == 1.0:
  665. return 'Yesterday'
  666. elif dt_diff_days < 7.0:
  667. return '%s days ago' % cint(dt_diff_days)
  668. elif dt_diff_days < 31.0:
  669. return '%s week(s) ago' % cint(math.ceil(dt_diff_days / 7.0))
  670. elif dt_diff_days < 365.0:
  671. return '%s months ago' % cint(math.ceil(dt_diff_days / 30.0))
  672. else:
  673. return 'more than %s year(s) ago' % cint(math.floor(dt_diff_days / 365.0))
  674. def execute_in_shell(cmd, verbose=0):
  675. # using Popen instead of os.system - as recommended by python docs
  676. from subprocess import Popen, PIPE
  677. p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
  678. # get err and output
  679. err, out = p.stderr.read(), p.stdout.read()
  680. if verbose:
  681. if err: print err
  682. if out: print out
  683. return err, out
  684. def comma_or(some_list):
  685. return comma_sep(some_list, " or ")
  686. def comma_and(some_list):
  687. return comma_sep(some_list, " and ")
  688. def comma_sep(some_list, sep):
  689. if isinstance(some_list, list):
  690. # ([] + some_list) is done to preserve the existing list
  691. some_list = [unicode(s) for s in ([] + some_list)]
  692. if not some_list:
  693. return ""
  694. elif len(some_list) == 1:
  695. return some_list[0]
  696. else:
  697. return ", ".join(some_list[:-1]) + sep + some_list[-1]
  698. else:
  699. return some_list