25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

__init__.py 23 KiB

13 yıl önce
13 yıl önce
12 yıl önce
14 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
12 yıl önce
11 yıl önce
11 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. # util __init__.py
  4. from __future__ import unicode_literals
  5. from werkzeug.test import Client
  6. import webnotes
  7. import os
  8. no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'FlexTable',
  9. 'Button', 'Image', 'Graph']
  10. default_fields = ['doctype', 'name', 'owner', 'creation', 'modified', 'modified_by',
  11. 'parent', 'parentfield', 'parenttype', 'idx', 'docstatus']
  12. # used in import_docs.py
  13. # TODO: deprecate it
  14. def getCSVelement(v):
  15. """
  16. Returns the CSV value of `v`, For example:
  17. * apple becomes "apple"
  18. * hi"there becomes "hi""there"
  19. """
  20. v = cstr(v)
  21. if not v: return ''
  22. if (',' in v) or ('\n' in v) or ('"' in v):
  23. if '"' in v: v = v.replace('"', '""')
  24. return '"'+v+'"'
  25. else: return v or ''
  26. def get_fullname(profile):
  27. """get the full name (first name + last name) of the user from Profile"""
  28. p = webnotes.conn.sql("""select first_name, last_name from `tabProfile`
  29. where name=%s""", profile, as_dict=1)
  30. if p:
  31. profile = " ".join(filter(None,
  32. [p[0].get('first_name'), p[0].get('last_name')])) or profile
  33. return profile
  34. def get_formatted_email(user):
  35. """get email id of user formatted as: John Doe <johndoe@example.com>"""
  36. if user == "Administrator":
  37. return user
  38. from email.utils import formataddr
  39. fullname = get_fullname(user)
  40. return formataddr((fullname, user))
  41. def extract_email_id(email):
  42. """fetch only the email part of the email id"""
  43. from email.utils import parseaddr
  44. fullname, email_id = parseaddr(email)
  45. if isinstance(email_id, basestring) and not isinstance(email_id, unicode):
  46. email_id = email_id.decode("utf-8", "ignore")
  47. return email_id
  48. def validate_email_add(email_str):
  49. """Validates the email string"""
  50. email = extract_email_id(email_str)
  51. import re
  52. 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])?", email.lower())
  53. def get_request_site_address(full_address=False):
  54. """get app url from request"""
  55. host_name = webnotes.local.conf.host_name
  56. if not host_name:
  57. if webnotes.request:
  58. protocol = 'https' == webnotes.get_request_header('X-Forwarded-Proto', "") and 'https://' or 'http://'
  59. host_name = protocol + webnotes.request.host
  60. elif webnotes.local.site:
  61. return "http://" + webnotes.local.site
  62. else:
  63. return "http://localhost"
  64. if full_address:
  65. return host_name + webnotes.get_request_header("REQUEST_URI", "")
  66. else:
  67. return host_name
  68. def random_string(length):
  69. """generate a random string"""
  70. import string
  71. from random import choice
  72. return ''.join([choice(string.letters + string.digits) for i in range(length)])
  73. def get_traceback():
  74. """
  75. Returns the traceback of the Exception
  76. """
  77. import sys, traceback
  78. exc_type, value, tb = sys.exc_info()
  79. trace_list = traceback.format_tb(tb, None) + \
  80. traceback.format_exception_only(exc_type, value)
  81. body = "Traceback (innermost last):\n" + "%-20s %s" % \
  82. (unicode((b"").join(trace_list[:-1]), 'utf-8'), unicode(trace_list[-1], 'utf-8'))
  83. if webnotes.logger:
  84. webnotes.logger.error('Db:'+(webnotes.conn and webnotes.conn.cur_db_name or '') \
  85. + ' - ' + body)
  86. return body
  87. def log(event, details):
  88. webnotes.logger.info(details)
  89. # datetime functions
  90. def getdate(string_date):
  91. """
  92. Coverts string date (yyyy-mm-dd) to datetime.date object
  93. """
  94. import datetime
  95. if isinstance(string_date, datetime.date):
  96. return string_date
  97. elif isinstance(string_date, datetime.datetime):
  98. return datetime.date()
  99. if " " in string_date:
  100. string_date = string_date.split(" ")[0]
  101. return datetime.datetime.strptime(string_date, "%Y-%m-%d").date()
  102. def add_to_date(date, years=0, months=0, days=0):
  103. """Adds `days` to the given date"""
  104. format = isinstance(date, basestring)
  105. if date:
  106. date = getdate(date)
  107. else:
  108. raise Exception, "Start date required"
  109. from dateutil.relativedelta import relativedelta
  110. date += relativedelta(years=years, months=months, days=days)
  111. if format:
  112. return date.strftime("%Y-%m-%d")
  113. else:
  114. return date
  115. def add_days(date, days):
  116. return add_to_date(date, days=days)
  117. def add_months(date, months):
  118. return add_to_date(date, months=months)
  119. def add_years(date, years):
  120. return add_to_date(date, years=years)
  121. def date_diff(string_ed_date, string_st_date):
  122. return (getdate(string_ed_date) - getdate(string_st_date)).days
  123. def time_diff(string_ed_date, string_st_date):
  124. return get_datetime(string_ed_date) - get_datetime(string_st_date)
  125. def time_diff_in_seconds(string_ed_date, string_st_date):
  126. return time_diff(string_ed_date, string_st_date).seconds
  127. def time_diff_in_hours(string_ed_date, string_st_date):
  128. return round(float(time_diff(string_ed_date, string_st_date).seconds) / 3600, 6)
  129. def now_datetime():
  130. from datetime import datetime
  131. return convert_utc_to_user_timezone(datetime.utcnow())
  132. def get_user_time_zone():
  133. if getattr(webnotes.local, "user_time_zone", None) is None:
  134. webnotes.local.user_time_zone = webnotes.cache().get_value("time_zone")
  135. if not webnotes.local.user_time_zone:
  136. webnotes.local.user_time_zone = webnotes.conn.get_value('Control Panel', None, 'time_zone') \
  137. or 'Asia/Calcutta'
  138. webnotes.cache().set_value("time_zone", webnotes.local.user_time_zone)
  139. return webnotes.local.user_time_zone
  140. def convert_utc_to_user_timezone(utc_timestamp):
  141. from pytz import timezone, UnknownTimeZoneError
  142. utcnow = timezone('UTC').localize(utc_timestamp)
  143. try:
  144. return utcnow.astimezone(timezone(get_user_time_zone()))
  145. except UnknownTimeZoneError:
  146. return utcnow
  147. def now():
  148. """return current datetime as yyyy-mm-dd hh:mm:ss"""
  149. if getattr(webnotes.local, "current_date", None):
  150. return getdate(webnotes.local.current_date).strftime("%Y-%m-%d") + " " + \
  151. now_datetime().strftime('%H:%M:%S')
  152. else:
  153. return now_datetime().strftime('%Y-%m-%d %H:%M:%S')
  154. def nowdate():
  155. """return current date as yyyy-mm-dd"""
  156. return now_datetime().strftime('%Y-%m-%d')
  157. def today():
  158. return nowdate()
  159. def nowtime():
  160. """return current time in hh:mm"""
  161. return now_datetime().strftime('%H:%M')
  162. def get_first_day(dt, d_years=0, d_months=0):
  163. """
  164. Returns the first day of the month for the date specified by date object
  165. Also adds `d_years` and `d_months` if specified
  166. """
  167. import datetime
  168. dt = getdate(dt)
  169. # d_years, d_months are "deltas" to apply to dt
  170. overflow_years, month = divmod(dt.month + d_months - 1, 12)
  171. year = dt.year + d_years + overflow_years
  172. return datetime.date(year, month + 1, 1)
  173. def get_last_day(dt):
  174. """
  175. Returns last day of the month using:
  176. `get_first_day(dt, 0, 1) + datetime.timedelta(-1)`
  177. """
  178. import datetime
  179. return get_first_day(dt, 0, 1) + datetime.timedelta(-1)
  180. def get_datetime(datetime_str):
  181. from datetime import datetime
  182. if isinstance(datetime_str, datetime):
  183. return datetime_str.replace(microsecond=0, tzinfo=None)
  184. return datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')
  185. def get_datetime_str(datetime_obj):
  186. if isinstance(datetime_obj, basestring):
  187. datetime_obj = get_datetime(datetime_obj)
  188. return datetime_obj.strftime('%Y-%m-%d %H:%M:%S')
  189. def formatdate(string_date=None):
  190. """
  191. Convers the given string date to :data:`user_format`
  192. User format specified in :term:`Control Panel`
  193. Examples:
  194. * dd-mm-yyyy
  195. * mm-dd-yyyy
  196. * dd/mm/yyyy
  197. """
  198. if string_date:
  199. string_date = getdate(string_date)
  200. else:
  201. string_date = now_datetime().date()
  202. if getattr(webnotes.local, "user_format", None) is None:
  203. webnotes.local.user_format = webnotes.conn.get_default("date_format")
  204. out = webnotes.local.user_format
  205. return out.replace("dd", string_date.strftime("%d"))\
  206. .replace("mm", string_date.strftime("%m"))\
  207. .replace("yyyy", string_date.strftime("%Y"))
  208. def global_date_format(date):
  209. """returns date as 1 January 2012"""
  210. formatted_date = getdate(date).strftime("%d %B %Y")
  211. return formatted_date.startswith("0") and formatted_date[1:] or formatted_date
  212. def dict_to_str(args, sep='&'):
  213. """
  214. Converts a dictionary to URL
  215. """
  216. import urllib
  217. t = []
  218. for k in args.keys():
  219. t.append(str(k)+'='+urllib.quote(str(args[k] or '')))
  220. return sep.join(t)
  221. def timestamps_equal(t1, t2):
  222. """Returns true if same the two string timestamps are same"""
  223. scrub = lambda x: x.replace(':', ' ').replace('-',' ').split()
  224. t1, t2 = scrub(t1), scrub(t2)
  225. if len(t1) != len(t2):
  226. return
  227. for i in range(len(t1)):
  228. if t1[i]!=t2[i]:
  229. return
  230. return 1
  231. def has_common(l1, l2):
  232. """Returns truthy value if there are common elements in lists l1 and l2"""
  233. return set(l1) & set(l2)
  234. def flt(s, precision=None):
  235. """Convert to float (ignore commas)"""
  236. if isinstance(s, basestring):
  237. s = s.replace(',','')
  238. try:
  239. num = float(s)
  240. if precision is not None:
  241. num = _round(num, precision)
  242. except Exception:
  243. num = 0
  244. return num
  245. def cint(s):
  246. """Convert to integer"""
  247. try: num = int(float(s))
  248. except: num = 0
  249. return num
  250. def cstr(s):
  251. if isinstance(s, unicode):
  252. return s
  253. elif s==None:
  254. return ''
  255. elif isinstance(s, basestring):
  256. return unicode(s, 'utf-8')
  257. else:
  258. return unicode(s)
  259. def _round(num, precision=0):
  260. """round method for round halfs to nearest even algorithm"""
  261. precision = cint(precision)
  262. multiplier = 10 ** precision
  263. # avoid rounding errors
  264. num = round(num * multiplier if precision else num, 8)
  265. import math
  266. floor = math.floor(num)
  267. decimal_part = num - floor
  268. if decimal_part == 0.5:
  269. num = floor if (floor % 2 == 0) else floor + 1
  270. else:
  271. num = round(num)
  272. return (num / multiplier) if precision else num
  273. def encode(obj, encoding="utf-8"):
  274. if isinstance(obj, list):
  275. out = []
  276. for o in obj:
  277. if isinstance(o, unicode):
  278. out.append(o.encode(encoding))
  279. else:
  280. out.append(o)
  281. return out
  282. elif isinstance(obj, unicode):
  283. return obj.encode(encoding)
  284. else:
  285. return obj
  286. def parse_val(v):
  287. """Converts to simple datatypes from SQL query results"""
  288. import datetime
  289. if isinstance(v, (datetime.date, datetime.datetime)):
  290. v = unicode(v)
  291. elif isinstance(v, datetime.timedelta):
  292. v = ":".join(unicode(v).split(":")[:2])
  293. elif isinstance(v, long):
  294. v = int(v)
  295. return v
  296. def fmt_money(amount, precision=None, currency=None):
  297. """
  298. Convert to string with commas for thousands, millions etc
  299. """
  300. number_format = webnotes.conn.get_default("number_format") or "#,###.##"
  301. decimal_str, comma_str, precision = get_number_format_info(number_format)
  302. amount = '%.*f' % (precision, flt(amount))
  303. if amount.find('.') == -1:
  304. decimals = ''
  305. else:
  306. decimals = amount.split('.')[1]
  307. parts = []
  308. minus = ''
  309. if flt(amount) < 0:
  310. minus = '-'
  311. amount = cstr(abs(flt(amount))).split('.')[0]
  312. if len(amount) > 3:
  313. parts.append(amount[-3:])
  314. amount = amount[:-3]
  315. val = number_format=="#,##,###.##" and 2 or 3
  316. while len(amount) > val:
  317. parts.append(amount[-val:])
  318. amount = amount[:-val]
  319. parts.append(amount)
  320. parts.reverse()
  321. amount = comma_str.join(parts) + (precision and (decimal_str + decimals) or "")
  322. amount = minus + amount
  323. if currency:
  324. symbol = webnotes.conn.get_value("Currency", currency, "symbol")
  325. if symbol:
  326. amount = symbol + " " + amount
  327. return amount
  328. number_format_info = {
  329. "#.###": ("", ".", 0),
  330. "#,###": ("", ",", 0),
  331. "#,###.##": (".", ",", 2),
  332. "#,##,###.##": (".", ",", 2),
  333. "#.###,##": (",", ".", 2),
  334. "# ###.##": (".", " ", 2),
  335. "#,###.###": (".", ",", 3),
  336. }
  337. def get_number_format_info(format):
  338. return number_format_info.get(format) or (".", ",", 2)
  339. #
  340. # convet currency to words
  341. #
  342. def money_in_words(number, main_currency = None, fraction_currency=None):
  343. """
  344. Returns string in words with currency and fraction currency.
  345. """
  346. d = get_defaults()
  347. if not main_currency:
  348. main_currency = d.get('currency', 'INR')
  349. if not fraction_currency:
  350. fraction_currency = webnotes.conn.get_value("Currency", main_currency, "fraction") or "Cent"
  351. n = "%.2f" % flt(number)
  352. main, fraction = n.split('.')
  353. if len(fraction)==1: fraction += '0'
  354. number_format = webnotes.conn.get_value("Currency", main_currency, "number_format") or \
  355. webnotes.conn.get_default("number_format") or "#,###.##"
  356. in_million = True
  357. if number_format == "#,##,###.##": in_million = False
  358. out = main_currency + ' ' + in_words(main, in_million).title()
  359. if cint(fraction):
  360. out = out + ' and ' + in_words(fraction, in_million).title() + ' ' + fraction_currency
  361. return out + ' only.'
  362. #
  363. # convert number to words
  364. #
  365. def in_words(integer, in_million=True):
  366. """
  367. Returns string in words for the given integer.
  368. """
  369. n=int(integer)
  370. known = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
  371. 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen',
  372. 19: 'nineteen', 20: 'twenty', 30: 'thirty', 40: 'forty', 50: 'fifty', 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety'}
  373. def psn(n, known, xpsn):
  374. import sys;
  375. if n in known: return known[n]
  376. bestguess, remainder = str(n), 0
  377. if n<=20:
  378. webnotes.errprint(sys.stderr)
  379. webnotes.errprint(n)
  380. webnotes.errprint("How did this happen?")
  381. assert 0
  382. elif n < 100:
  383. bestguess= xpsn((n//10)*10, known, xpsn) + '-' + xpsn(n%10, known, xpsn)
  384. return bestguess
  385. elif n < 1000:
  386. bestguess= xpsn(n//100, known, xpsn) + ' ' + 'hundred'
  387. remainder = n%100
  388. else:
  389. if in_million:
  390. if n < 1000000:
  391. bestguess= xpsn(n//1000, known, xpsn) + ' ' + 'thousand'
  392. remainder = n%1000
  393. elif n < 1000000000:
  394. bestguess= xpsn(n//1000000, known, xpsn) + ' ' + 'million'
  395. remainder = n%1000000
  396. else:
  397. bestguess= xpsn(n//1000000000, known, xpsn) + ' ' + 'billion'
  398. remainder = n%1000000000
  399. else:
  400. if n < 100000:
  401. bestguess= xpsn(n//1000, known, xpsn) + ' ' + 'thousand'
  402. remainder = n%1000
  403. elif n < 10000000:
  404. bestguess= xpsn(n//100000, known, xpsn) + ' ' + 'lakh'
  405. remainder = n%100000
  406. else:
  407. bestguess= xpsn(n//10000000, known, xpsn) + ' ' + 'crore'
  408. remainder = n%10000000
  409. if remainder:
  410. if remainder >= 100:
  411. comma = ','
  412. else:
  413. comma = ''
  414. return bestguess + comma + ' ' + xpsn(remainder, known, xpsn)
  415. else:
  416. return bestguess
  417. return psn(n, known, psn)
  418. # Get Defaults
  419. # ==============================================================================
  420. def get_defaults(key=None):
  421. """
  422. Get dictionary of default values from the :term:`Control Panel`, or a value if key is passed
  423. """
  424. return webnotes.conn.get_defaults(key)
  425. def set_default(key, val):
  426. """
  427. Set / add a default value to :term:`Control Panel`
  428. """
  429. return webnotes.conn.set_default(key, val)
  430. def remove_blanks(d):
  431. """
  432. Returns d with empty ('' or None) values stripped
  433. """
  434. empty_keys = []
  435. for key in d:
  436. if d[key]=='' or d[key]==None:
  437. # del d[key] raises runtime exception, using a workaround
  438. empty_keys.append(key)
  439. for key in empty_keys:
  440. del d[key]
  441. return d
  442. def pprint_dict(d, level=1, no_blanks=True):
  443. """
  444. Pretty print a dictionary with indents
  445. """
  446. if no_blanks:
  447. remove_blanks(d)
  448. # make indent
  449. indent, ret = '', ''
  450. for i in range(0,level): indent += '\t'
  451. # add lines
  452. comment, lines = '', []
  453. kl = d.keys()
  454. kl.sort()
  455. # make lines
  456. for key in kl:
  457. if key != '##comment':
  458. tmp = {key: d[key]}
  459. lines.append(indent + str(tmp)[1:-1] )
  460. # add comment string
  461. if '##comment' in kl:
  462. ret = ('\n' + indent) + '# ' + d['##comment'] + '\n'
  463. # open
  464. ret += indent + '{\n'
  465. # lines
  466. ret += indent + ',\n\t'.join(lines)
  467. # close
  468. ret += '\n' + indent + '}'
  469. return ret
  470. def get_common(d1,d2):
  471. """
  472. returns (list of keys) the common part of two dicts
  473. """
  474. return [p for p in d1 if p in d2 and d1[p]==d2[p]]
  475. def get_common_dict(d1, d2):
  476. """
  477. return common dictionary of d1 and d2
  478. """
  479. ret = {}
  480. for key in d1:
  481. if key in d2 and d2[key]==d1[key]:
  482. ret[key] = d1[key]
  483. return ret
  484. def get_diff_dict(d1, d2):
  485. """
  486. return common dictionary of d1 and d2
  487. """
  488. diff_keys = set(d2.keys()).difference(set(d1.keys()))
  489. ret = {}
  490. for d in diff_keys: ret[d] = d2[d]
  491. return ret
  492. def get_file_timestamp(fn):
  493. """
  494. Returns timestamp of the given file
  495. """
  496. from webnotes.utils import cint
  497. try:
  498. return str(cint(os.stat(fn).st_mtime))
  499. except OSError, e:
  500. if e.args[0]!=2:
  501. raise
  502. else:
  503. return None
  504. # to be deprecated
  505. def make_esc(esc_chars):
  506. """
  507. Function generator for Escaping special characters
  508. """
  509. return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
  510. # esc / unescape characters -- used for command line
  511. def esc(s, esc_chars):
  512. """
  513. Escape special characters
  514. """
  515. if not s:
  516. return ""
  517. for c in esc_chars:
  518. esc_str = '\\' + c
  519. s = s.replace(c, esc_str)
  520. return s
  521. def unesc(s, esc_chars):
  522. """
  523. UnEscape special characters
  524. """
  525. for c in esc_chars:
  526. esc_str = '\\' + c
  527. s = s.replace(esc_str, c)
  528. return s
  529. def is_html(text):
  530. out = False
  531. for key in ["<br>", "<p", "<img", "<div"]:
  532. if key in text:
  533. out = True
  534. break
  535. return out
  536. def strip_html(text):
  537. """
  538. removes anything enclosed in and including <>
  539. """
  540. import re
  541. return re.compile(r'<.*?>').sub('', text)
  542. def escape_html(text):
  543. html_escape_table = {
  544. "&": "&amp;",
  545. '"': "&quot;",
  546. "'": "&apos;",
  547. ">": "&gt;",
  548. "<": "&lt;",
  549. }
  550. return "".join(html_escape_table.get(c,c) for c in text)
  551. def get_doctype_label(dt=None):
  552. """
  553. Gets label of a doctype
  554. """
  555. if dt:
  556. res = webnotes.conn.sql("""\
  557. SELECT name, dt_label FROM `tabDocType Label`
  558. WHERE name=%s""", dt)
  559. return res and res[0][0] or dt
  560. else:
  561. res = webnotes.conn.sql("SELECT name, dt_label FROM `tabDocType Label`")
  562. dt_label_dict = {}
  563. for r in res:
  564. dt_label_dict[r[0]] = r[1]
  565. return dt_label_dict
  566. def get_label_doctype(label):
  567. """
  568. Gets doctype from its label
  569. """
  570. res = webnotes.conn.sql("""\
  571. SELECT name FROM `tabDocType Label`
  572. WHERE dt_label=%s""", label)
  573. return res and res[0][0] or label
  574. def pretty_date(iso_datetime):
  575. """
  576. Takes an ISO time and returns a string representing how
  577. long ago the date represents.
  578. Ported from PrettyDate by John Resig
  579. """
  580. if not iso_datetime: return ''
  581. from datetime import datetime
  582. import math
  583. if isinstance(iso_datetime, basestring):
  584. iso_datetime = datetime.strptime(iso_datetime, '%Y-%m-%d %H:%M:%S')
  585. now_dt = datetime.strptime(now(), '%Y-%m-%d %H:%M:%S')
  586. dt_diff = now_dt - iso_datetime
  587. # available only in python 2.7+
  588. # dt_diff_seconds = dt_diff.total_seconds()
  589. dt_diff_seconds = dt_diff.days * 86400.0 + dt_diff.seconds
  590. dt_diff_days = math.floor(dt_diff_seconds / 86400.0)
  591. # differnt cases
  592. if dt_diff_seconds < 60.0:
  593. return 'just now'
  594. elif dt_diff_seconds < 120.0:
  595. return '1 minute ago'
  596. elif dt_diff_seconds < 3600.0:
  597. return '%s minutes ago' % cint(math.floor(dt_diff_seconds / 60.0))
  598. elif dt_diff_seconds < 7200.0:
  599. return '1 hour ago'
  600. elif dt_diff_seconds < 86400.0:
  601. return '%s hours ago' % cint(math.floor(dt_diff_seconds / 3600.0))
  602. elif dt_diff_days == 1.0:
  603. return 'Yesterday'
  604. elif dt_diff_days < 7.0:
  605. return '%s days ago' % cint(dt_diff_days)
  606. elif dt_diff_days < 31.0:
  607. return '%s week(s) ago' % cint(math.ceil(dt_diff_days / 7.0))
  608. elif dt_diff_days < 365.0:
  609. return '%s months ago' % cint(math.ceil(dt_diff_days / 30.0))
  610. else:
  611. return 'more than %s year(s) ago' % cint(math.floor(dt_diff_days / 365.0))
  612. def execute_in_shell(cmd, verbose=0):
  613. # using Popen instead of os.system - as recommended by python docs
  614. from subprocess import Popen
  615. import tempfile
  616. with tempfile.TemporaryFile() as stdout:
  617. with tempfile.TemporaryFile() as stderr:
  618. p = Popen(cmd, shell=True, stdout=stdout, stderr=stderr)
  619. p.wait()
  620. stdout.seek(0)
  621. out = stdout.read()
  622. stderr.seek(0)
  623. err = stderr.read()
  624. if verbose:
  625. if err: print err
  626. if out: print out
  627. return err, out
  628. def comma_or(some_list):
  629. return comma_sep(some_list, " or ")
  630. def comma_and(some_list):
  631. return comma_sep(some_list, " and ")
  632. def comma_sep(some_list, sep):
  633. if isinstance(some_list, (list, tuple)):
  634. # list(some_list) is done to preserve the existing list
  635. some_list = [unicode(s) for s in list(some_list)]
  636. if not some_list:
  637. return ""
  638. elif len(some_list) == 1:
  639. return some_list[0]
  640. else:
  641. some_list = ["'%s'" % s for s in some_list]
  642. return ", ".join(some_list[:-1]) + sep + some_list[-1]
  643. else:
  644. return some_list
  645. def filter_strip_join(some_list, sep):
  646. """given a list, filter None values, strip spaces and join"""
  647. return (cstr(sep)).join((cstr(a).strip() for a in filter(None, some_list)))
  648. def get_path(*path, **kwargs):
  649. base = kwargs.get('base')
  650. if not base:
  651. base = webnotes.local.site_path
  652. return os.path.join(base, *path)
  653. def get_site_base_path(sites_dir=None, hostname=None):
  654. return webnotes.local.site_path
  655. def get_site_path(*path):
  656. return get_path(base=get_site_base_path(), *path)
  657. def get_files_path():
  658. return get_site_path("public", "files")
  659. def get_backups_path():
  660. return get_site_path("public", "backup")
  661. def get_url(uri=None):
  662. url = get_request_site_address()
  663. if not url or "localhost" in url:
  664. subdomain = webnotes.conn.get_value("Website Settings", "Website Settings",
  665. "subdomain")
  666. if subdomain:
  667. if "http" not in subdomain:
  668. url = "http://" + subdomain
  669. if uri:
  670. import urllib
  671. url = urllib.basejoin(url, uri)
  672. return url
  673. def get_url_to_form(doctype, name, base_url=None, label=None):
  674. if not base_url:
  675. base_url = get_url()
  676. if not label: label = name
  677. return """<a href="%(base_url)s/app.html#!Form/%(doctype)s/%(name)s">%(label)s</a>""" % locals()
  678. def encode_dict(d, encoding="utf-8"):
  679. for key in d:
  680. if isinstance(d[key], basestring) and isinstance(d[key], unicode):
  681. d[key] = d[key].encode(encoding)
  682. return d
  683. def decode_dict(d, encoding="utf-8"):
  684. for key in d:
  685. if isinstance(d[key], basestring) and not isinstance(d[key], unicode):
  686. d[key] = d[key].decode(encoding, "ignore")
  687. return d
  688. import operator
  689. operator_map = {
  690. # startswith
  691. "^": lambda (a, b): (a or "").startswith(b),
  692. # in or not in a list
  693. "in": lambda (a, b): operator.contains(b, a),
  694. "not in": lambda (a, b): not operator.contains(b, a),
  695. # comparison operators
  696. "=": lambda (a, b): operator.eq(a, b),
  697. "!=": lambda (a, b): operator.ne(a, b),
  698. ">": lambda (a, b): operator.gt(a, b),
  699. "<": lambda (a, b): operator.lt(a, b),
  700. ">=": lambda (a, b): operator.ge(a, b),
  701. "<=": lambda (a, b): operator.le(a, b),
  702. "not None": lambda (a, b): a and True or False,
  703. "None": lambda (a, b): (not a) and True or False
  704. }
  705. def compare(val1, condition, val2):
  706. ret = False
  707. if condition in operator_map:
  708. ret = operator_map[condition]((val1, val2))
  709. return ret
  710. def get_site_name(hostname):
  711. return hostname.split(':')[0]
  712. def get_disk_usage():
  713. """get disk usage of files folder"""
  714. files_path = get_files_path()
  715. if not os.path.exists(files_path):
  716. return 0
  717. err, out = execute_in_shell("du -hsm {files_path}".format(files_path=files_path))
  718. return cint(out.split("\n")[-2].split("\t")[0])
  719. def expand_partial_links(html):
  720. import re
  721. url = get_url()
  722. if not url.endswith("/"): url += "/"
  723. return re.sub('(href|src){1}([\s]*=[\s]*[\'"]?)((?!http)[^\'" >]+)([\'"]?)',
  724. '\g<1>\g<2>{}\g<3>\g<4>'.format(url),
  725. html)
  726. def touch_file(path):
  727. with open(path, 'a'):
  728. os.utime(path, None)
  729. return True
  730. def get_test_client():
  731. from webnotes.app import application
  732. return Client(application)