core.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. # -*- coding: utf-8 -*-
  2. """
  3. demeter
  4. name:core.py
  5. author:rabin
  6. """
  7. import time
  8. import os
  9. import signal
  10. import re
  11. import sys
  12. import json
  13. import subprocess
  14. import importlib
  15. import logging
  16. class Demeter(object):
  17. path = ''
  18. root = ''
  19. config = {}
  20. option = {}
  21. web = ''
  22. request = False
  23. route = []
  24. def __new__(self, *args, **kwargs):
  25. sys.exit()
  26. def __init__(self):
  27. pass
  28. @staticmethod
  29. def checkPy3():
  30. if sys.version > '3':
  31. state = True
  32. else:
  33. state = False
  34. return state
  35. @classmethod
  36. def getConfig(self):
  37. state = self.checkPy3()
  38. if state:
  39. import configparser
  40. return configparser.ConfigParser()
  41. else:
  42. import ConfigParser
  43. return ConfigParser.ConfigParser()
  44. @staticmethod
  45. def isset(v):
  46. try :
  47. type (eval(v))
  48. except :
  49. return 0
  50. else :
  51. return 1
  52. @classmethod
  53. def initConfig(self):
  54. self.path = File.path()
  55. self.root = File.cur_path()
  56. if self.config == {}:
  57. filename = self.path + 'conf/'+self.getConfigName()+'.conf'
  58. if File.exists(filename):
  59. config = self.getConfig()
  60. config.read(filename)
  61. for item in config.sections():
  62. self.config[item] = self.readConfig(config, item)
  63. return True
  64. else:
  65. Demeter.echo(filename + ' is not exists')
  66. sys.exit()
  67. @classmethod
  68. def getConfigName(self):
  69. name = 'dev'
  70. if 'DEMETER_CONF' in os.environ:
  71. name = os.environ['DEMETER_CONF']
  72. param = {}
  73. param['config'] = 'c'
  74. self.getopt(param)
  75. if 'config' in self.option and self.option['config']:
  76. name = self.option['config']
  77. return name
  78. @staticmethod
  79. def readConfig(config, type):
  80. value = config.options(type)
  81. result = {}
  82. for item in value:
  83. result[item] = config.get(type, item)
  84. return result
  85. @classmethod
  86. def getopt(self, param = {}):
  87. import getopt
  88. param['help'] = 'h'
  89. shortopts = ''
  90. longopts = []
  91. check = []
  92. for k,v in param.items():
  93. if k == 'help':
  94. shortopts = shortopts + v
  95. else:
  96. shortopts = shortopts + v + ':'
  97. longopts.append(k)
  98. try:
  99. options, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
  100. for name, value in options:
  101. for k,v in param.items():
  102. if name in ('-' + v, '--' + k):
  103. if k == 'help':
  104. self.usage()
  105. else:
  106. self.option[k] = value
  107. except getopt.GetoptError:
  108. #self.usage()
  109. return
  110. @classmethod
  111. def usage(self, name = 'usage'):
  112. file = self.path + name
  113. if not File.exists(file):
  114. file = self.root + name
  115. self.echo(File.read(file))
  116. sys.exit()
  117. @classmethod
  118. def temp(self, key='', name='', value=''):
  119. temp = Demeter.path + 'conf/temp.conf'
  120. if File.exists(temp):
  121. config = self.getConfig()
  122. config.read(temp)
  123. if key and name:
  124. config.set(key, name, value)
  125. config.write(open(temp, 'w'))
  126. else:
  127. result = {}
  128. for item in config.sections():
  129. result[item] = self.readConfig(config, item)
  130. return result
  131. @classmethod
  132. def echo(self, args):
  133. import pprint
  134. pprint.pprint(args)
  135. @classmethod
  136. def record(self, key, value):
  137. # 记录日志
  138. # self.log(key, value)
  139. service = self.service('record')
  140. service.push(key, value)
  141. @classmethod
  142. def service(self, name):
  143. self.initConfig()
  144. path = 'service.'
  145. if name == 'common':
  146. path = 'demeter.'
  147. name = 'service'
  148. service = self.getClass(name, path)
  149. return service()
  150. @classmethod
  151. def adminModel(self, table):
  152. self.initConfig()
  153. config = ('manage_admin', 'manage_log', 'manage_role')
  154. if table in config:
  155. return self.getClass(table, 'demeter.admin.model.')
  156. return False
  157. @classmethod
  158. def model(self, table, name='rdb'):
  159. self.initConfig()
  160. name = self.config['db'][name]
  161. config = self.config[name]
  162. obj = self.getObject('db', 'demeter.')
  163. db = getattr(obj, name.capitalize())
  164. connect = db(config).get()
  165. model = self.adminModel(table)
  166. if not model:
  167. model = self.getClass(table, 'model.')
  168. return model(name, connect, config)
  169. @classmethod
  170. def getMethod(self, module):
  171. import inspect
  172. return inspect.getmembers(module, callable)
  173. @classmethod
  174. def getPackage(self, package):
  175. import pkgutil
  176. for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__, prefix=package.__name__ + '.', onerror=lambda x: None):
  177. yield modname
  178. @staticmethod
  179. def getObject(name, path = ''):
  180. return importlib.import_module(path + name)
  181. """
  182. @classmethod
  183. def getObject(self, name, path = ''):
  184. module = __import__(path + name)
  185. return getattr(module, name)
  186. """
  187. @classmethod
  188. def getClass(self, name, path=''):
  189. obj = self.getObject(name, path)
  190. return getattr(obj, name.capitalize())
  191. @staticmethod
  192. def bool(value, type = 'db'):
  193. if type == 'mysql':
  194. value = value == str(True)
  195. if value == True:
  196. return '1'
  197. else:
  198. return '2'
  199. else:
  200. return value == str(True)
  201. @classmethod
  202. def runtime(self, path, file, content=''):
  203. path = self.path + 'runtime/' + path + '/'
  204. File.mkdir(path)
  205. file = path + file
  206. if File.exists(file):
  207. return False
  208. else:
  209. File.write(file, content)
  210. return True
  211. @classmethod
  212. def webInit(self, name):
  213. self.initConfig()
  214. self.web = name
  215. self.webPath = self.path + self.web + '/'
  216. if self.web == 'admin':
  217. self.webPath = self.root + self.web + '/'
  218. self.getObject('main', name + '.')
  219. @classmethod
  220. def md5(self, value, salt=False):
  221. import hashlib
  222. if salt:
  223. if salt == True:
  224. salt = self.rand()
  225. value = value + salt
  226. return hashlib.md5(value.encode("utf-8")).hexdigest() + '_' + salt
  227. else:
  228. return hashlib.md5(value.encode("utf-8")).hexdigest()
  229. @classmethod
  230. def sha1(self, value, salt=False):
  231. import hashlib
  232. if salt:
  233. if salt == True:
  234. salt = self.rand()
  235. value = value + salt
  236. return hashlib.sha1(value.encode("utf-8")).hexdigest() + '_' + salt
  237. else:
  238. return hashlib.sha1(value.encode("utf-8")).hexdigest()
  239. @classmethod
  240. def rand(self, length = 4):
  241. module = self.getObject('random')
  242. rand = getattr(module, 'randint')
  243. salt = ''
  244. chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
  245. len_chars = len(chars) - 1
  246. for i in range(length):
  247. salt += chars[rand(0, len_chars)]
  248. return salt
  249. @classmethod
  250. def hash(self):
  251. return self.md5(str(time.clock()))
  252. @classmethod
  253. def uuid(self, value):
  254. import uuid
  255. return str(uuid.uuid5(uuid.uuid1(), value))
  256. @staticmethod
  257. def hour(value):
  258. if value < 10:
  259. return '0' + str(value)
  260. return value
  261. @staticmethod
  262. def time():
  263. return int(time.time())
  264. @staticmethod
  265. def mktime(value, string='%Y-%m-%d %H:%M:%S'):
  266. if ' ' in string and ' ' not in value:
  267. value = value + ' 00:00:00'
  268. return int(time.mktime(time.strptime(value,string)))
  269. @classmethod
  270. def date(self, value, string='%Y-%m-%d %H:%M:%S'):
  271. module = self.getObject('datetime')
  272. datetime = getattr(module, 'datetime')
  273. fromtimestamp = getattr(datetime, 'fromtimestamp')
  274. return str(fromtimestamp(value).strftime(string))
  275. @staticmethod
  276. def isJson(value):
  277. result = False
  278. try:
  279. result = json.loads(value)
  280. except ValueError:
  281. return result
  282. return result
  283. @staticmethod
  284. def host(value):
  285. import urllib
  286. protocol, s1 = urllib.splittype(value)
  287. value, s2 = urllib.splithost(s1)
  288. value, port = urllib.splitport(value)
  289. return value
  290. @staticmethod
  291. def compressUuid(value):
  292. row = value.replace('-', '')
  293. code = ''
  294. hash = [x for x in "0123456789-abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
  295. for i in xrange(10):
  296. enbin = "%012d" % int(bin(int(row[i * 3] + row[i * 3 + 1] + row[i * 3 + 2], 16))[2:], 10)
  297. code += (hash[int(enbin[0:6], 2)] + hash[int(enbin[6:12], 2)])
  298. return code
  299. @staticmethod
  300. def checkMobile(request):
  301. if 'Demeter-Mobile' in request.headers:
  302. return True
  303. userAgent = request.headers['User-Agent']
  304. # userAgent = env.get('HTTP_USER_AGENT')
  305. _long_matches = r'googlebot-mobile|android|avantgo|blackberry|blazer|elaine|hiptop|ip(hone|od)|kindle|midp|mmp|mobile|o2|opera mini|palm( os)?|pda|plucker|pocket|psp|smartphone|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce; (iemobile|ppc)|xiino|maemo|fennec'
  306. _long_matches = re.compile(_long_matches, re.IGNORECASE)
  307. _short_matches = r'1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-'
  308. _short_matches = re.compile(_short_matches, re.IGNORECASE)
  309. if _long_matches.search(userAgent) != None:
  310. return True
  311. user_agent = userAgent[0:4]
  312. if _short_matches.search(user_agent) != None:
  313. return True
  314. return False
  315. @staticmethod
  316. def exp(exp, value):
  317. if exp:
  318. exp = exp.replace('{n}', value)
  319. value = str(eval(exp))
  320. return value
  321. @classmethod
  322. def curl(self, url = '', param={}, method = 'get'):
  323. import requests
  324. if method == 'get':
  325. req = requests.get(url, params=param)
  326. else:
  327. req = requests.post(url, params=param)
  328. result = req.text
  329. return result
  330. @classmethod
  331. def out(self, msg='', data={}, code=0, callback='', function=''):
  332. if data:
  333. if 'page' in data and data['page']['total'] <= 0:
  334. del data['page']
  335. if 'update' in data and not data['update']:
  336. del data['update']
  337. if 'search' in data and not data['search']:
  338. del data['search']
  339. result = ''
  340. send = {}
  341. send['status'] = 1
  342. send['msg'] = msg
  343. send['data'] = data
  344. send['code'] = code
  345. if not send['data']:
  346. send['status'] = 2
  347. result = json.dumps(send)
  348. if callback:
  349. result = callback + '(' + result + ')'
  350. elif function:
  351. result = '<script>parent.' + function + '(' + result + ')' + '</script>';
  352. return result
  353. @classmethod
  354. def error(self, string):
  355. if self.request:
  356. self.request.out(string)
  357. else:
  358. self.echo(string)
  359. #os._exit(0)
  360. @classmethod
  361. def redis(self):
  362. self.initConfig()
  363. import redis
  364. config = self.config['redis']
  365. pool = redis.ConnectionPool(host=config['host'], password=config['password'], port=int(config['port']))
  366. return redis.Redis(connection_pool=pool)
  367. class Log(object):
  368. @staticmethod
  369. def get(name):
  370. formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  371. logger = logging.getLogger(name)
  372. logger.setLevel(logging.INFO)
  373. path = File.path() + 'runtime/log/'
  374. File.mkdir(path)
  375. file_handler = logging.handlers.RotatingFileHandler(os.path.join(path, 'vecan.log'), maxBytes=1024*1024,backupCount=5)
  376. file_handler.setLevel(level=logging.DEBUG)
  377. file_handler.setFormatter(formatter)
  378. logger.addHandler(file_handler)
  379. return logger
  380. class File(object):
  381. @staticmethod
  382. def write(file, content):
  383. handle = open(file, 'w')
  384. handle.write(content)
  385. handle.close()
  386. Shell.popen('chmod +x ' + file)
  387. @staticmethod
  388. def read(path, name = ''):
  389. handle = open(path + name, 'r')
  390. content = handle.read()
  391. handle.close()
  392. return content
  393. @staticmethod
  394. def readContent(path, name = ''):
  395. content = ''
  396. handle = open(path + name, 'r')
  397. while True:
  398. line = handle.readline()
  399. if line:
  400. line = line.rstrip("\n")
  401. content = content + line
  402. else:
  403. break
  404. handle.close()
  405. return content
  406. @staticmethod
  407. def cur_path():
  408. return os.path.split(os.path.realpath(__file__))[0] + '/'
  409. @staticmethod
  410. def getFiles(path):
  411. return os.listdir(path)
  412. @staticmethod
  413. def path():
  414. return os.sys.path[0] + '/'
  415. @staticmethod
  416. def exists(name):
  417. return os.path.exists(name)
  418. @staticmethod
  419. def rename(old, new):
  420. return os.rename(old, new)
  421. @staticmethod
  422. def remove(file):
  423. return os.remove(file)
  424. @staticmethod
  425. def mkdir(path):
  426. if File.exists(path) == False:
  427. os.mkdir(path)
  428. return path
  429. @staticmethod
  430. def mkdirs(path):
  431. if File.exists(path) == False:
  432. os.makedirs(path)
  433. return path
  434. @staticmethod
  435. def ext(path):
  436. return os.path.splitext(path)[1]
  437. class Shell(object):
  438. @staticmethod
  439. def popen(command, sub=False, bg=False, timeout=0):
  440. string = command
  441. if bg == True:
  442. command = command + ' 1>/dev/null 2>&1 &'
  443. if timeout > 0:
  444. proc = subprocess.Popen(command,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True, close_fds=True, preexec_fn = os.setsid)
  445. poll_seconds = .250
  446. deadline = time.time() + timeout
  447. while time.time() < deadline and proc.poll() == None:
  448. time.sleep(poll_seconds)
  449. if proc.poll() == None:
  450. os.killpg(proc.pid, signal.SIGTERM)
  451. return 'timeout'
  452. stdout,stderr = proc.communicate()
  453. return stdout
  454. elif sub == False:
  455. process = os.popen(command)
  456. output = process.read()
  457. process.close()
  458. return output
  459. else:
  460. popen = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
  461. output = ''
  462. Demeter.echo(string)
  463. while True:
  464. output = popen.stdout.readline()
  465. Demeter.echo(output)
  466. if popen.poll() is not None:
  467. break
  468. return output
  469. class Check(object):
  470. @staticmethod
  471. def match(rule, value):
  472. if not rule.match(value):
  473. return False
  474. return True
  475. @staticmethod
  476. def mobile(value):
  477. rule = re.compile(r'1\d{10}')
  478. return Check.match(rule, value)
  479. @staticmethod
  480. def number(value):
  481. try:
  482. int(value)
  483. return True
  484. except ValueError:
  485. return False
  486. @staticmethod
  487. def numberFloat(value):
  488. try:
  489. float(value)
  490. return True
  491. except ValueError:
  492. return False