core.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  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 shutil
  11. import re
  12. import sys
  13. import json
  14. import subprocess
  15. import importlib
  16. #import fire
  17. from watchdog.observers import Observer
  18. from watchdog.events import FileSystemEventHandler
  19. class Demeter(object):
  20. path = ''
  21. root = ''
  22. config = {}
  23. option = {}
  24. web = ''
  25. request = False
  26. route = []
  27. logger = False
  28. dog = False
  29. syncData = {}
  30. def __new__(self, *args, **kwargs):
  31. sys.exit()
  32. def __init__(self):
  33. pass
  34. @staticmethod
  35. def checkPy3():
  36. if sys.version > '3':
  37. state = True
  38. else:
  39. state = False
  40. return state
  41. @classmethod
  42. def getConfig(self):
  43. state = self.checkPy3()
  44. if state:
  45. import configparser
  46. return configparser.ConfigParser()
  47. else:
  48. import ConfigParser
  49. return ConfigParser.ConfigParser()
  50. @staticmethod
  51. def isset(v):
  52. try :
  53. type (eval(v))
  54. except :
  55. return 0
  56. else :
  57. return 1
  58. @classmethod
  59. def initConfig(self):
  60. if not self.path:
  61. self.path = File.path()
  62. self.root = File.cur_path()
  63. if self.config == {}:
  64. filename = self.path + 'conf/'+self.getConfigName()+'.conf'
  65. if File.exists(filename):
  66. config = self.getConfig()
  67. config.read(filename)
  68. for item in config.sections():
  69. self.config[item] = self.readConfig(config, item)
  70. return True
  71. else:
  72. self.path = self.path + '../'
  73. return self.initConfig()
  74. #Demeter.echo(filename + ' is not exists')
  75. #sys.exit()
  76. @classmethod
  77. def getConfigName(self):
  78. name = 'dev'
  79. if 'DEMETER_CONF' in os.environ:
  80. name = os.environ['DEMETER_CONF']
  81. param = {}
  82. param['config'] = 'c'
  83. self.getopt(param)
  84. if 'config' in self.option and self.option['config']:
  85. name = self.option['config']
  86. return name
  87. @staticmethod
  88. def readConfig(config, type):
  89. value = config.options(type)
  90. result = {}
  91. for item in value:
  92. result[item] = config.get(type, item)
  93. return result
  94. @classmethod
  95. def getopt(self, param = {}):
  96. import getopt
  97. param['help'] = 'h'
  98. shortopts = ''
  99. longopts = []
  100. check = []
  101. for k,v in param.items():
  102. if k == 'help':
  103. shortopts = shortopts + v
  104. else:
  105. shortopts = shortopts + v + ':'
  106. longopts.append(k)
  107. try:
  108. options, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
  109. for name, value in options:
  110. for k,v in param.items():
  111. if name in ('-' + v, '--' + k):
  112. if k == 'help':
  113. self.usage()
  114. else:
  115. self.option[k] = value
  116. except getopt.GetoptError:
  117. #self.usage()
  118. return
  119. @classmethod
  120. def usage(self, name = 'usage'):
  121. file = self.path + name
  122. if not File.exists(file):
  123. file = self.root + name
  124. self.echo(File.read(file))
  125. sys.exit()
  126. @classmethod
  127. def temp(self, key='', name='', value=''):
  128. temp = Demeter.path + 'conf/temp.conf'
  129. if File.exists(temp):
  130. config = self.getConfig()
  131. config.read(temp)
  132. if key and name:
  133. config.set(key, name, value)
  134. config.write(open(temp, 'w'))
  135. else:
  136. result = {}
  137. for item in config.sections():
  138. result[item] = self.readConfig(config, item)
  139. return result
  140. @classmethod
  141. def echo(self, args):
  142. import pprint
  143. pprint.pprint(args)
  144. @classmethod
  145. def record(self, key, value):
  146. # 记录日志
  147. # self.log(key, value)
  148. service = self.service('record')
  149. service.push(key, value)
  150. @classmethod
  151. def service(self, name, parent = ''):
  152. return self.load(name, parent, 'service')
  153. @classmethod
  154. def load(self, name, parent = '', base = 'service'):
  155. self.initConfig()
  156. path = base + '.'
  157. if name == 'common':
  158. path = 'demeter.'
  159. name = base
  160. if parent:
  161. path = path + parent + '.'
  162. load = self.getClass(name, path)
  163. return load()
  164. @classmethod
  165. def adminModel(self, table):
  166. self.initConfig()
  167. config = ('manage_admin', 'manage_log', 'manage_role')
  168. if table in config:
  169. return self.getClass(table, 'demeter.admin.model.')
  170. return False
  171. @classmethod
  172. def model(self, table, name='rdb'):
  173. self.initConfig()
  174. name = self.config['db'][name]
  175. config = self.config[name]
  176. obj = self.getObject('db', 'demeter.')
  177. db = getattr(obj, name.capitalize())
  178. connect = db(config).get()
  179. model = self.adminModel(table)
  180. if not model:
  181. model = self.getClass(table, 'model.')
  182. return model(name, connect, config)
  183. @classmethod
  184. def getMethod(self, module):
  185. import inspect
  186. return inspect.getmembers(module, callable)
  187. @classmethod
  188. def getPackage(self, package):
  189. import pkgutil
  190. for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__, prefix=package.__name__ + '.', onerror=lambda x: None):
  191. yield modname
  192. @classmethod
  193. def getPath(self, path):
  194. import pkgutil
  195. for importer, modname, ispkg in pkgutil.walk_packages(path):
  196. loader = importer.find_module(modname)
  197. mod = loader.load_module(modname)
  198. yield mod
  199. @staticmethod
  200. def getObject(name, path = ''):
  201. return importlib.import_module(path + name)
  202. """
  203. @classmethod
  204. def getObject(self, name, path = ''):
  205. module = __import__(path + name)
  206. return getattr(module, name)
  207. """
  208. @classmethod
  209. def getClass(self, name, path=''):
  210. obj = self.getObject(name, path)
  211. return getattr(obj, name.capitalize())
  212. @staticmethod
  213. def bool(value, type = 'db'):
  214. if type == 'mysql':
  215. value = value == str(True)
  216. if value == True:
  217. return '1'
  218. else:
  219. return '2'
  220. else:
  221. return value == str(True)
  222. @classmethod
  223. def runtime(self, path, file, content=''):
  224. path = self.path + 'runtime/' + path + '/'
  225. File.mkdir(path)
  226. file = path + file
  227. if File.exists(file):
  228. return False
  229. else:
  230. File.write(file, content)
  231. return True
  232. @classmethod
  233. def webInit(self, name):
  234. self.initConfig()
  235. self.web = name
  236. self.webPath = self.path + self.web + '/'
  237. if self.web == 'admin':
  238. self.webPath = self.root + self.web + '/'
  239. self.getObject('main', name + '.')
  240. @classmethod
  241. def md5(self, value, salt=False):
  242. import hashlib
  243. if salt:
  244. if salt == True:
  245. salt = self.rand()
  246. value = value + salt
  247. return hashlib.md5(value.encode("utf-8")).hexdigest() + '_' + salt
  248. else:
  249. return hashlib.md5(value.encode("utf-8")).hexdigest()
  250. @classmethod
  251. def sha1(self, value, salt=False):
  252. import hashlib
  253. if salt:
  254. if salt == True:
  255. salt = self.rand()
  256. value = value + salt
  257. return hashlib.sha1(value.encode("utf-8")).hexdigest() + '_' + salt
  258. else:
  259. return hashlib.sha1(value.encode("utf-8")).hexdigest()
  260. @classmethod
  261. def range(self, length):
  262. if self.checkPy3():
  263. return range(length)
  264. else:
  265. return xrange(length)
  266. @classmethod
  267. def rand(self, length = 4):
  268. module = self.getObject('random')
  269. rand = getattr(module, 'randint')
  270. salt = ''
  271. chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
  272. len_chars = len(chars) - 1
  273. l = Demeter.range(length)
  274. for i in l:
  275. salt += chars[rand(0, len_chars)]
  276. return salt
  277. @classmethod
  278. def hash(self):
  279. return self.md5(str(time.clock()))
  280. @classmethod
  281. def uuid(self, value):
  282. import uuid
  283. return str(uuid.uuid5(uuid.uuid1(), value))
  284. @staticmethod
  285. def hour(value):
  286. if value < 10:
  287. return '0' + str(value)
  288. return value
  289. @staticmethod
  290. def time():
  291. return int(time.time())
  292. @staticmethod
  293. def mktime(value, string='%Y-%m-%d %H:%M:%S'):
  294. if ' ' in string and ' ' not in value:
  295. value = value + ' 00:00:00'
  296. return int(time.mktime(time.strptime(value,string)))
  297. @classmethod
  298. def date(self, value, string='%Y-%m-%d %H:%M:%S'):
  299. module = self.getObject('datetime')
  300. datetime = getattr(module, 'datetime')
  301. fromtimestamp = getattr(datetime, 'fromtimestamp')
  302. return str(fromtimestamp(value).strftime(string))
  303. @staticmethod
  304. def isJson(value):
  305. result = False
  306. try:
  307. result = json.loads(value)
  308. except ValueError:
  309. return result
  310. return result
  311. @staticmethod
  312. def host(value):
  313. import urllib
  314. protocol, s1 = urllib.splittype(value)
  315. value, s2 = urllib.splithost(s1)
  316. value, port = urllib.splitport(value)
  317. return value
  318. @staticmethod
  319. def compressUuid(value):
  320. row = value.replace('-', '')
  321. code = ''
  322. hash = [x for x in "0123456789-abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
  323. l = Demeter.range(10)
  324. for i in l:
  325. enbin = "%012d" % int(bin(int(row[i * 3] + row[i * 3 + 1] + row[i * 3 + 2], 16))[2:], 10)
  326. code += (hash[int(enbin[0:6], 2)] + hash[int(enbin[6:12], 2)])
  327. return code
  328. @staticmethod
  329. def checkMobile(request):
  330. if 'Demeter-Mobile' in request.headers:
  331. return True
  332. userAgent = request.headers['User-Agent']
  333. # userAgent = env.get('HTTP_USER_AGENT')
  334. _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'
  335. _long_matches = re.compile(_long_matches, re.IGNORECASE)
  336. _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\-'
  337. _short_matches = re.compile(_short_matches, re.IGNORECASE)
  338. if _long_matches.search(userAgent) != None:
  339. return True
  340. user_agent = userAgent[0:4]
  341. if _short_matches.search(user_agent) != None:
  342. return True
  343. return False
  344. @staticmethod
  345. def exp(exp, value):
  346. if exp:
  347. exp = exp.replace('{n}', value)
  348. value = str(eval(exp))
  349. return value
  350. @classmethod
  351. def curl(self, url = '', param={}, method = 'get', timeout=5, max=2):
  352. import requests
  353. from requests.adapters import HTTPAdapter
  354. try:
  355. s = requests.Session()
  356. s.mount('http://', HTTPAdapter(max_retries=max))
  357. s.mount('https://', HTTPAdapter(max_retries=max))
  358. if method == 'get':
  359. req = s.get(url, params=param, timeout=timeout)
  360. else:
  361. req = s.post(url, params=param, timeout=timeout)
  362. result = req.text
  363. except requests.exceptions.RequestException as e:
  364. result = False
  365. return result
  366. @classmethod
  367. def out(self, msg='', data={}, code=0, callback='', function=''):
  368. if data:
  369. if 'page' in data and data['page']['total'] <= 0:
  370. del data['page']
  371. if 'update' in data and not data['update']:
  372. del data['update']
  373. if 'search' in data and not data['search']:
  374. del data['search']
  375. result = ''
  376. send = {}
  377. send['status'] = 1
  378. send['msg'] = msg
  379. send['data'] = data
  380. send['code'] = code
  381. if not send['data']:
  382. send['status'] = 2
  383. result = json.dumps(send)
  384. if callback:
  385. result = callback + '(' + result + ')'
  386. elif function:
  387. result = '<script>parent.' + function + '(' + result + ')' + '</script>';
  388. return result
  389. @classmethod
  390. def error(self, string):
  391. if self.request:
  392. self.request.out(string)
  393. else:
  394. self.echo(string)
  395. #os._exit(0)
  396. @classmethod
  397. def redis(self):
  398. self.initConfig()
  399. import redis
  400. config = self.config['redis']
  401. pool = redis.ConnectionPool(host=config['host'], password=config['password'], port=int(config['port']))
  402. return redis.Redis(connection_pool=pool)
  403. @classmethod
  404. def sync(self, table, id):
  405. table = table.replace('demeter_', '')
  406. if 'sync' in Demeter.config:
  407. config = Demeter.config['sync']['table'].split(',')
  408. service = Demeter.config['sync']['service'].split(',')
  409. if table in config and table not in self.syncData:
  410. Demeter.service(service[0], service[1]).rsync(table, id)
  411. #self.syncData[table] = True
  412. class Log(object):
  413. @classmethod
  414. def init(self, name, output = False):
  415. import logging
  416. from logging.handlers import RotatingFileHandler
  417. formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  418. logger = logging.getLogger(name)
  419. logger.setLevel(logging.DEBUG)
  420. if output:
  421. stream_handler = logging.StreamHandler(sys.stderr)
  422. stream_handler.setFormatter(formatter)
  423. logger.addHandler(stream_handler)
  424. file_handler = RotatingFileHandler(self.file(name), maxBytes=1024*1024,backupCount=5)
  425. file_handler.setLevel(level=logging.DEBUG)
  426. file_handler.setFormatter(formatter)
  427. logger.addHandler(file_handler)
  428. return logger
  429. @classmethod
  430. def read(self, name, lines=200):
  431. file = self.file(name)
  432. if File.exists(file):
  433. return File.tail(file, lines)
  434. return ''
  435. @classmethod
  436. def file(self, name):
  437. path = File.path() + 'runtime/log/'
  438. File.mkdir(path)
  439. return os.path.join(path, name + '.log')
  440. class WatchDog(object):
  441. @staticmethod
  442. def init(path = [], reloads = [], recursive = False):
  443. event_handler = WatchDogHandle(reloads)
  444. dog = Observer()
  445. base = File.path()
  446. if not path:
  447. path = ['conf/',]
  448. for item in path:
  449. dog.schedule(event_handler, base + item, recursive=recursive)
  450. dog.start()
  451. return dog
  452. class WatchDogHandle(FileSystemEventHandler):
  453. @classmethod
  454. def __init__(self, reloads = False):
  455. FileSystemEventHandler.__init__(self)
  456. self.reloads = reloads
  457. @classmethod
  458. def on_modified(self, event):
  459. if not event.is_directory and '.' in event.src_path:
  460. if self.reloads:
  461. for item in self.reloads:
  462. item.reload()
  463. elif Demeter.web:
  464. Demeter.webInit(Demeter.web)
  465. else:
  466. Demeter.echo('modify ' + event.src_path)
  467. class File(object):
  468. @staticmethod
  469. def write(file, content):
  470. handle = open(file, 'w')
  471. handle.write(content)
  472. handle.close()
  473. Shell.popen('chmod +x ' + file)
  474. @staticmethod
  475. def read(path, name = ''):
  476. handle = open(path + name, 'r')
  477. content = handle.read()
  478. handle.close()
  479. return content
  480. @staticmethod
  481. def readContent(path, name = ''):
  482. content = ''
  483. handle = open(path + name, 'r')
  484. while True:
  485. line = handle.readline()
  486. if line:
  487. line = line.rstrip("\n")
  488. content = content + line
  489. else:
  490. break
  491. handle.close()
  492. return content
  493. @staticmethod
  494. def cur_path():
  495. return os.path.split(os.path.realpath(__file__))[0] + '/'
  496. @staticmethod
  497. def getFiles(path):
  498. return os.listdir(path)
  499. @staticmethod
  500. def path():
  501. return os.sys.path[0] + '/'
  502. @staticmethod
  503. def exists(name):
  504. return os.path.exists(name)
  505. @staticmethod
  506. def rename(old, new):
  507. return os.rename(old, new)
  508. @classmethod
  509. def remove(self, file):
  510. if isinstance(file, str) and self.exists(file):
  511. if os.path.isfile(file):
  512. return os.remove(file)
  513. else:
  514. # 删除非空目录
  515. return shutil.rmtree(file)
  516. return False
  517. @staticmethod
  518. def mkdir(path):
  519. if File.exists(path) == False:
  520. os.mkdir(path)
  521. return path
  522. @staticmethod
  523. def mkdirs(path):
  524. if File.exists(path) == False:
  525. os.makedirs(path)
  526. return path
  527. @staticmethod
  528. def ext(path):
  529. return os.path.splitext(path)[1]
  530. @classmethod
  531. def runtime(self, path = 'data'):
  532. return self.mkdir(self.path() + 'runtime/' + path + '/')
  533. """
  534. 实现 tail -n
  535. """
  536. @classmethod
  537. def tail(self, filepath, n=10):
  538. PAGE = 4096
  539. res = ""
  540. with open(filepath, 'rb') as f:
  541. f_len = f.seek(0, 2)
  542. rem = f_len % PAGE
  543. page_n = f_len // PAGE
  544. r_len = rem if rem else PAGE
  545. while True:
  546. # 如果读取的页大小>=文件大小,直接读取数据输出
  547. if r_len >= f_len:
  548. f.seek(0)
  549. lines = f.readlines()[::-1]
  550. break
  551. f.seek(-r_len, 2)
  552. # print('f_len: {}, rem: {}, page_n: {}, r_len: {}'.format(f_len, rem, page_n, r_len))
  553. lines = f.readlines()[::-1]
  554. count = len(lines) -1 # 末行可能不完整,减一行,加大读取量
  555. if count >= n: # 如果读取到的行数>=指定行数,则退出循环读取数据
  556. break
  557. else: # 如果读取行数不够,载入更多的页大小读取数据
  558. r_len += PAGE
  559. page_n -= 1
  560. for line in lines[:n][::-1]:
  561. res += line.decode('utf-8')
  562. return res
  563. class Shell(object):
  564. @staticmethod
  565. def popen(command, sub=False, bg=False, timeout=0):
  566. string = command
  567. if bg == True:
  568. command = command + ' 1>/dev/null 2>&1 &'
  569. if timeout > 0:
  570. proc = subprocess.Popen(command,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True, close_fds=True, preexec_fn = os.setsid)
  571. poll_seconds = .250
  572. deadline = time.time() + timeout
  573. while time.time() < deadline and proc.poll() == None:
  574. time.sleep(poll_seconds)
  575. if proc.poll() == None:
  576. os.killpg(proc.pid, signal.SIGTERM)
  577. return 'timeout'
  578. stdout,stderr = proc.communicate()
  579. return stdout
  580. elif sub == False:
  581. process = os.popen(command)
  582. output = process.read()
  583. process.close()
  584. return output
  585. else:
  586. popen = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
  587. output = ''
  588. Demeter.echo(string)
  589. while True:
  590. output = popen.stdout.readline()
  591. Demeter.echo(output)
  592. if popen.poll() is not None:
  593. break
  594. return output
  595. class Check(object):
  596. @staticmethod
  597. def match(rule, value):
  598. if not rule.match(value):
  599. return False
  600. return True
  601. @staticmethod
  602. def mobile(value):
  603. rule = re.compile(r'1\d{10}')
  604. return Check.match(rule, value)
  605. @staticmethod
  606. def number(value):
  607. try:
  608. int(value)
  609. return True
  610. except ValueError:
  611. return False
  612. @staticmethod
  613. def numberFloat(value):
  614. try:
  615. float(value)
  616. return True
  617. except ValueError:
  618. return False