deva 1.2.3__tar.gz → 1.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {deva-1.2.3 → deva-1.2.4}/PKG-INFO +1 -1
  2. {deva-1.2.3 → deva-1.2.4}/deva/__init__.py +1 -1
  3. {deva-1.2.3 → deva-1.2.4}/deva/core.py +5 -2
  4. {deva-1.2.3 → deva-1.2.4}/deva/endpoints.py +4 -4
  5. {deva-1.2.3 → deva-1.2.4}/deva/namespace.py +13 -2
  6. {deva-1.2.3 → deva-1.2.4}/deva/sources.py +115 -124
  7. deva-1.2.4/deva/topic.py +165 -0
  8. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/PKG-INFO +1 -1
  9. {deva-1.2.3 → deva-1.2.4}/setup.py +1 -1
  10. deva-1.2.3/deva/topic.py +0 -94
  11. {deva-1.2.3 → deva-1.2.4}/MANIFEST.in +0 -0
  12. {deva-1.2.3 → deva-1.2.4}/README.rst +0 -0
  13. {deva-1.2.3 → deva-1.2.4}/deva/bus.py +0 -0
  14. {deva-1.2.3 → deva-1.2.4}/deva/compute.py +0 -0
  15. {deva-1.2.3 → deva-1.2.4}/deva/dask.py +0 -0
  16. {deva-1.2.3 → deva-1.2.4}/deva/future.py +0 -0
  17. {deva-1.2.3 → deva-1.2.4}/deva/graph.py +0 -0
  18. {deva-1.2.3 → deva-1.2.4}/deva/lambdas.py +0 -0
  19. {deva-1.2.3 → deva-1.2.4}/deva/monitor.py +0 -0
  20. {deva-1.2.3 → deva-1.2.4}/deva/page.py +0 -0
  21. {deva-1.2.3 → deva-1.2.4}/deva/pipe.py +0 -0
  22. {deva-1.2.3 → deva-1.2.4}/deva/river.py +0 -0
  23. {deva-1.2.3 → deva-1.2.4}/deva/sample/.DS_Store +0 -0
  24. {deva-1.2.3 → deva-1.2.4}/deva/sample/bus/bus_in.py +0 -0
  25. {deva-1.2.3 → deva-1.2.4}/deva/sample/bus/bus_out.py +0 -0
  26. {deva-1.2.3 → deva-1.2.4}/deva/sample/crawler/.DS_Store +0 -0
  27. {deva-1.2.3 → deva-1.2.4}/deva/sample/crawler/asynchttp.py +0 -0
  28. {deva-1.2.3 → deva-1.2.4}/deva/sample/matmul.py +0 -0
  29. {deva-1.2.3 → deva-1.2.4}/deva/sample/my_future.py +0 -0
  30. {deva-1.2.3 → deva-1.2.4}/deva/sample/search/.DS_Store +0 -0
  31. {deva-1.2.3 → deva-1.2.4}/deva/sample/search/cpiplog.db +0 -0
  32. {deva-1.2.3 → deva-1.2.4}/deva/sample/search/search_sql.py +0 -0
  33. {deva-1.2.3 → deva-1.2.4}/deva/sample/search/search_stream.py +0 -0
  34. {deva-1.2.3 → deva-1.2.4}/deva/sample/webview/stream_page.py +0 -0
  35. {deva-1.2.3 → deva-1.2.4}/deva/sample/when/scheduler.py +0 -0
  36. {deva-1.2.3 → deva-1.2.4}/deva/sample/when/timer.py +0 -0
  37. {deva-1.2.3 → deva-1.2.4}/deva/sample/when/worker.py +0 -0
  38. {deva-1.2.3 → deva-1.2.4}/deva/search.py +0 -0
  39. {deva-1.2.3 → deva-1.2.4}/deva/state.py +0 -0
  40. {deva-1.2.3 → deva-1.2.4}/deva/store.py +0 -0
  41. {deva-1.2.3 → deva-1.2.4}/deva/templates/monitor.html +0 -0
  42. {deva-1.2.3 → deva-1.2.4}/deva/templates/stream.html +0 -0
  43. {deva-1.2.3 → deva-1.2.4}/deva/templates/streams.html +0 -0
  44. {deva-1.2.3 → deva-1.2.4}/deva/templates/xterm.css +0 -0
  45. {deva-1.2.3 → deva-1.2.4}/deva/templates/xterm.js +0 -0
  46. {deva-1.2.3 → deva-1.2.4}/deva/utils/__init__.py +0 -0
  47. {deva-1.2.3 → deva-1.2.4}/deva/utils/simhash.py +0 -0
  48. {deva-1.2.3 → deva-1.2.4}/deva/utils/sqlitedict.py +0 -0
  49. {deva-1.2.3 → deva-1.2.4}/deva/utils/whooshalchemy.py +0 -0
  50. {deva-1.2.3 → deva-1.2.4}/deva/when.py +0 -0
  51. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/SOURCES.txt +0 -0
  52. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/dependency_links.txt +0 -0
  53. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/not-zip-safe +0 -0
  54. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/requires.txt +0 -0
  55. {deva-1.2.3 → deva-1.2.4}/deva.egg-info/top_level.txt +0 -0
  56. {deva-1.2.3 → deva-1.2.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deva
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: data eval in future
5
5
  Home-page: https://github.com/sostc/deva
6
6
  Author: spark
@@ -25,4 +25,4 @@ try:
25
25
  except ImportError:
26
26
  pass
27
27
 
28
- __version__ = '1.2.3'
28
+ __version__ = '1.2.4'
@@ -993,14 +993,17 @@ def httpx(req, render=False, **kwargs):
993
993
  if isinstance(req, str):
994
994
  response = yield httpclient.get(req)
995
995
  elif isinstance(req, dict):
996
- response = yield httpclient.get(**req)
996
+ if req.get('method') == 'post':
997
+ response = yield httpclient.post(**req)
998
+ else:
999
+ response = yield httpclient.get(**req)
997
1000
 
998
1001
  if render:
999
1002
  yield response.html.arender(**kwargs)
1000
1003
 
1001
1004
  return response
1002
1005
  except Exception as e:
1003
- (req, e) >> print
1006
+ print(req, e)
1004
1007
  logger.exception(e)
1005
1008
 
1006
1009
 
@@ -156,10 +156,8 @@ class Dtalk(Stream):
156
156
  msg = str(msg)
157
157
 
158
158
  data = {"msgtype": "text", "text": {"content": msg},
159
- "at": {"atMobiles": [], "isAtAll": False}}
160
- if '@all' in msg:
161
- data = {"msgtype": "text", "text": {"content": msg},
162
- "at": {"atMobiles": [], "isAtAll": True}}
159
+ "at": {"atMobiles": [], "isAtAll": '@all' in msg}}
160
+
163
161
  if msg.startswith('@md@'):
164
162
  # @md@财联社新闻汇总|text
165
163
  content = msg[4:]
@@ -171,6 +169,8 @@ class Dtalk(Stream):
171
169
  }
172
170
 
173
171
  post_data = json.JSONEncoder().encode(data)
172
+ # import urllib
173
+ # post_data = urllib.parse.urlencode(data)
174
174
 
175
175
  headers = {'Content-Type': 'application/json'}
176
176
 
@@ -17,13 +17,14 @@ Example usage::
17
17
 
18
18
  from .core import Stream
19
19
  from .store import DBStream, X
20
- from .topic import Topic
20
+ from .topic import Topic, TCPTopic
21
21
 
22
22
 
23
23
  class Namespace(dict):
24
24
  def __init__(self):
25
25
  self['stream'] = {}
26
26
  self['topic'] = {}
27
+ self['tcptopic'] = {}
27
28
  self['table'] = {}
28
29
  self['data'] = {}
29
30
  self['webserver'] = {}
@@ -32,7 +33,8 @@ class Namespace(dict):
32
33
  constructor = {'stream': Stream,
33
34
  'topic': Topic,
34
35
  'table': DBStream,
35
- 'data': X, }
36
+ 'data': X,
37
+ 'tcptopic': TCPTopic}
36
38
 
37
39
  if typ == 'webserver':
38
40
  from .page import PageServer
@@ -75,6 +77,15 @@ def NT(name='', *args, **kwargs):
75
77
  return None
76
78
 
77
79
 
80
+ def NWT(name='', *args, **kwargs):
81
+
82
+ try:
83
+ return namespace.create(typ='tcptopic', name=name, *args, **kwargs)
84
+ except Exception as e:
85
+ print(e)
86
+ return None
87
+
88
+
78
89
  def NB(name, *args, **kwargs):
79
90
  """创建命名的DBStream.
80
91
 
@@ -1,4 +1,3 @@
1
- import pandas as pd
2
1
  import subprocess
3
2
  import json
4
3
  from tornado.web import RequestHandler, Application
@@ -12,15 +11,14 @@ from glob import glob
12
11
  import os
13
12
  import tornado.ioloop
14
13
 
15
- from .topic import RedisStream
16
14
  from .core import Stream
17
- from .namespace import NB, NS
18
15
 
19
16
  import logging
20
17
  import asyncio
21
18
 
22
- from urllib.parse import unquote
23
19
 
20
+ import aioredis
21
+ import time
24
22
 
25
23
  logger = logging.getLogger(__name__)
26
24
 
@@ -512,6 +510,84 @@ class from_kafka(Source):
512
510
  self.stopped = True
513
511
 
514
512
 
513
+ @Stream.register_api(staticmethod)
514
+ class RedisStream(Stream):
515
+ """redis stream,read and write.
516
+
517
+
518
+ 上游进来的写入redis ,redis的读出来的压入下游,
519
+ exapmle::
520
+
521
+ news = Stream.RedisStream('news')
522
+ l = list()
523
+ news>>l
524
+ for i in range(1000):
525
+ i>>news
526
+
527
+ l|len
528
+
529
+ """
530
+
531
+ def __init__(self, topic, start=True,
532
+ group=None, address='localhost', db=0, password=None, **kwargs):
533
+ self.topic = topic
534
+ self.redis_address = address
535
+ self.redis_password = password
536
+ self.group = group or hash(self)+hash(time.time())
537
+ self.consumer = hash(self)
538
+
539
+ super(RedisStream, self).__init__(ensure_io_loop=True, **kwargs)
540
+ self.redis = None
541
+ self.stopped = True
542
+ if start:
543
+ self.start()
544
+
545
+ @gen.coroutine
546
+ def process(self):
547
+ if not self.redis:
548
+ self.redis = yield aioredis.Redis(host=self.redis_address, password=self.redis_password)
549
+
550
+ topic_exists = yield self.redis.exists(self.topic)
551
+ if not topic_exists:
552
+ print('create topic:', self.topic)
553
+ yield self.redis.xadd(self.topic, {'data': dill.dumps('go')})
554
+ try:
555
+ yield self.redis.xgroup_create(self.topic, self.group)
556
+ except Exception as e:
557
+ print(e)
558
+
559
+ while True:
560
+ results = yield self.redis.xread(count=10, block=500, streams={self.topic: '$'})
561
+ if results:
562
+ for result in results:
563
+ print('rec:', result)
564
+ data = dill.loads(result[1][0][1][b'data'])
565
+ self._emit(data)
566
+
567
+ if self.stopped:
568
+ break
569
+
570
+ @gen.coroutine
571
+ def _send(self, data):
572
+ if not self.redis:
573
+ self.redis = yield aioredis.Redis(host=self.redis_address, password=self.redis_password)
574
+ x = yield self.redis.xadd(self.topic, {'data': dill.dumps(data)}, maxlen=20)
575
+ print('send:', x)
576
+
577
+ def emit(self, x, asynchronous=True):
578
+ self.loop.add_callback(self._send, x)
579
+ return x
580
+
581
+ def start(self):
582
+ if self.stopped:
583
+ self.stopped = False
584
+ self.loop.add_callback(self.process)
585
+
586
+ def stop(self,):
587
+ self.stopped = True
588
+ self.loop.add_callback(self.redis.close)
589
+
590
+
515
591
  @Stream.register_api(staticmethod)
516
592
  class from_redis(Stream):
517
593
  def __init__(self, topic, group=None, max_len=100, **kwargs):
@@ -586,21 +662,21 @@ class from_http_request(Stream):
586
662
 
587
663
 
588
664
  class StreamTCPServer(TCPServer):
589
- """
590
- server.in_s
591
- server.out_s
592
- """
593
-
594
665
  def __init__(self, port=2345, **kwargs):
595
666
  self.delimiter = 'zjw-split-0358'.encode('utf-8')
596
667
  self.out_s = Stream()
597
668
  self.in_s = Stream()
669
+
670
+ # 进来的数据,处理后,再发出去。
671
+ self.in_s >> self.out_s
672
+
598
673
  super(StreamTCPServer, self).__init__(**kwargs)
599
674
  self.handlers = dict()
600
675
  self.listen(port)
601
676
 
602
677
  def __rrshift__(self, x):
603
- x >> self.out_s
678
+ # 进入消息来源之一,直接塞入数据
679
+ x >> self.in_s
604
680
 
605
681
  @gen.coroutine
606
682
  def handle_stream(self, stream, address):
@@ -609,17 +685,22 @@ class StreamTCPServer(TCPServer):
609
685
  stream.write(x)
610
686
  stream.write(self.delimiter)
611
687
  except StreamClosedError:
612
- logger.exception('%s connect close' % str(address))
688
+ print('%s connect close' % str(address))
613
689
  self.handlers.get(address).destroy()
614
690
  del self.handlers[address]
615
691
 
692
+ # 将客户端io输出挂载到分发管道 ,出去的消息,dill后写出
616
693
  self.handlers[address] = self.out_s.map(dill.dumps).sink(_write)
694
+
695
+ # 进入消息来源之二,不停的读取网络消息
617
696
  while True:
618
697
  try:
619
698
  data = yield stream.read_until(self.delimiter)
620
- yield self.in_s._emit(dill.loads(data))
699
+ # 进入消息来源之一、服务端读取客户端消息后放入接收管道
700
+ yield self.in_s.emit(dill.loads(data))
701
+ # yield self.out_s._emit(dill.loads(data))
621
702
  except StreamClosedError:
622
- logger.exception('%s connect close' % str(address))
703
+ print('%s connect close' % str(address))
623
704
  break
624
705
 
625
706
  def stop(self):
@@ -632,8 +713,10 @@ class StreamTCPServer(TCPServer):
632
713
 
633
714
  class StreamTCPClient():
634
715
  """从tcp端口订阅数据
635
- client.in_s
636
- client.out_s
716
+ c1 = StreamTCPClient("127.0.0.1", 23)
717
+ c1.start()
718
+ client = StreamTCPClient(host='127.0.0.1',port=2345)
719
+ client2 = StreamTCPClient()
637
720
 
638
721
  """
639
722
 
@@ -642,37 +725,44 @@ class StreamTCPClient():
642
725
  self.host = host
643
726
  self.port = port
644
727
  self.delimiter = 'zjw-split-0358'.encode('utf-8')
645
- self.out_s = Stream()
646
- self.in_s = Stream(ensure_io_loop=True)
728
+
729
+ self.out_s = Stream() # 发去服务端
730
+ self.in_s = Stream(ensure_io_loop=True) # 进入消息
647
731
  self._stream = None
648
732
  self.in_s.filter(lambda x: x == 'exit').sink(lambda x: self.stop())
733
+ self.stopped = True
649
734
  self.start()
650
735
 
651
736
  def __rrshift__(self, x):
737
+ # 直接发消息去服务端
652
738
  x >> self.out_s
653
739
 
654
740
  @gen.coroutine
655
741
  def start(self):
656
742
  try:
657
743
  self._stream = yield TCPClient().connect(self.host, self.port)
744
+ self.stopped = False
658
745
  except Exception as e:
659
- logger.exception(e, 'connect', self.host, self.port, 'error')
746
+ print(e, 'connect', self.host, self.port, 'error')
660
747
 
661
748
  def _write(x):
662
749
  try:
663
750
  self._stream.write(x)
664
751
  self._stream.write(self.delimiter)
665
752
  except StreamClosedError:
666
- logger.exception(f'{self.host}:{self.port} connect close')
753
+ print(f'{self.host}:{self.port} connect close')
667
754
  self.out_handler.destroy()
668
755
 
756
+ # 将客户端io输出挂载到分发管道
669
757
  self.out_handler = self.out_s.map(dill.dumps).sink(_write)
670
- # try:
758
+ #
671
759
  while self._stream:
672
- data = yield self._stream.read_until(self.delimiter)
673
- yield self.in_s.emit(dill.loads(data))
674
- # except iostream.StreamClosedError:
675
- # logger.exception('tornado.iostream.StreamClosedError')
760
+ try:
761
+ data = yield self._stream.read_until(self.delimiter)
762
+ yield self.in_s.emit(dill.loads(data))
763
+ except StreamClosedError:
764
+ print('tornado.iostream.StreamClosedError')
765
+ break
676
766
 
677
767
  def stop(self):
678
768
  if not self._stream.closed() and self._stream.close():
@@ -689,6 +779,7 @@ class from_mail(Source):
689
779
  starttls=False,
690
780
  interval=60*15, start=False, **kwargs):
691
781
  from imbox import Imbox
782
+ from .namespace import NB
692
783
  if not host:
693
784
  try:
694
785
  hostname = NB('mail')['hostname']
@@ -753,106 +844,6 @@ class from_periodic(Source):
753
844
  await asyncio.sleep(self._poll)
754
845
 
755
846
 
756
- @Stream.register_api(staticmethod)
757
- class http_topic(Stream):
758
- """Receive data from http request,emit httprequest data to stream."""
759
-
760
- def __init__(self, port=7777, path='/.*', start=False, server_kwargs=None):
761
- self.port = port
762
- self.path = path
763
- self.server_kwargs = server_kwargs or {}
764
- super(http_topic, self).__init__(ensure_io_loop=True)
765
- self.stopped = True
766
- self.server = None
767
- if start: # pragma: no cover
768
- self.start()
769
-
770
- def _start_server(self):
771
- class Handler(RequestHandler):
772
- source = self
773
-
774
- def _loads(self, body):
775
- """解析从web端口提交过来的数据.
776
-
777
- 可能的数据有字符串和二进制,
778
- 字符串可能是直接字符串,也可能是json编码后的字符串
779
- 二进制可能是图像等直接可用的二进制,也可能是dill编码的二进制pyobject
780
- """
781
- try:
782
- body = dill.loads(body)
783
- except TypeError:
784
- body = json.loads(body)
785
- try:
786
- body = pd.DataFrame.from_dict(body)
787
- except:
788
- body = body
789
- except ValueError:
790
- body = body.decode('utf-8')
791
- finally:
792
- return body
793
-
794
- def _encode(self, body):
795
- if isinstance(body, pd.DataFrame):
796
- return body.sample(20).to_html()
797
- else:
798
- return json.dumps(body, ensure_ascii=False)
799
-
800
- @gen.coroutine
801
- def post(self):
802
- body = dill.loads(self.request.body)
803
- body = [self._loads(i) for i in body]
804
- if not isinstance(body, list):
805
- body = [body]
806
-
807
- tag = unquote(self.request.headers['tag'])
808
- print(tag)
809
- if tag:
810
- source = NS(tag)
811
- if not source.is_cache:
812
- source.start_cache(5, 64*64*24*5)
813
- else:
814
- source = self.source
815
- for i in body:
816
- yield source._emit(i)
817
- self.write('OK')
818
-
819
- @gen.coroutine
820
- def get(self):
821
- topic = unquote(self.request.path)
822
- if topic == '/':
823
- data = self.source.recent()
824
- else:
825
- stream = NS(topic.split('/')[1])
826
- if not stream.is_cache:
827
- stream.start_cache(10, 64*64*24*7)
828
- data = stream.recent()
829
- if 'deva' in self.request.headers['User-Agent']:
830
- self.write(dill.dumps(data))
831
- else:
832
- for i in data:
833
- self.write(self._encode(i)+'</br>')
834
-
835
- self.application = Application([
836
- (self.path, Handler),
837
- ])
838
- # self.server = HTTPServer(application, **self.server_kwargs)
839
- self.server = self.application.listen(self.port)
840
-
841
- def start(self):
842
- if self.stopped:
843
- self.stopped = False
844
- self._start_server()
845
- self.start_cache(5, 60*60*48)
846
- # self.loop.add_callback(self._start_server)#这个会导致在端口占用情况下不报错
847
-
848
- def stop(self):
849
- """Shutdown HTTP server."""
850
- if not self.stopped:
851
- self.server.stop()
852
- self.server = None
853
- self.stopped = True
854
-
855
-
856
847
  def gen_block_test() -> int:
857
848
  import time
858
849
  import datetime
@@ -0,0 +1,165 @@
1
+ from .core import Stream
2
+ # from tornado import gen
3
+ import logging
4
+ import os
5
+ from .sources import StreamTCPClient, RedisStream
6
+ from urllib.parse import unquote
7
+ from tornado.web import RequestHandler, Application
8
+ import pandas as pd
9
+ import dill
10
+ from tornado import gen
11
+ import json
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ @Stream.register_api()
17
+ class Topic(RedisStream):
18
+
19
+ def __init__(self, name='', group=str(os.getpid()), maxsize=None, **kwargs):
20
+ super().__init__(topic=name,
21
+ group=group,
22
+ start=True,
23
+ name=name,
24
+ **kwargs)
25
+
26
+
27
+ @Stream.register_api(staticmethod)
28
+ class TCPStream(Stream):
29
+ """redis stream,read and write.
30
+
31
+
32
+ 上游进来的写入,读出来的压入下游,
33
+ exapmle::
34
+
35
+ bus = TCPStream()
36
+ bus>>log
37
+ bus2 = TCPStream()
38
+ bus2.map(lambda x:x*2)>>log
39
+
40
+ """
41
+
42
+ def __init__(self, host='127.0.0.1', port=2345, topic='', **kwargs):
43
+ self.topic = topic
44
+ super(TCPStream, self).__init__(ensure_io_loop=True, **kwargs)
45
+ try:
46
+ self.client = StreamTCPClient(host=host, port=port)
47
+ # 进来的消息发下游
48
+ self.client.in_s.sink(lambda x: self._emit(x))
49
+ except Exception as e:
50
+ print(e)
51
+
52
+ def emit(self, x, asynchronous=True):
53
+ x >> self.client
54
+
55
+
56
+ @Stream.register_api()
57
+ class TCPTopic(TCPStream):
58
+
59
+ def __init__(self, name='', **kwargs):
60
+ super().__init__(topic=name,
61
+ name=name,
62
+ **kwargs)
63
+
64
+
65
+ @Stream.register_api(staticmethod)
66
+ class http_topic(Stream):
67
+
68
+ """Receive data from http request,emit httprequest data to stream."""
69
+
70
+ def __init__(self, port=7777, path='/.*', start=False, server_kwargs=None):
71
+ self.port = port
72
+ self.path = path
73
+ self.server_kwargs = server_kwargs or {}
74
+ super(http_topic, self).__init__(ensure_io_loop=True)
75
+ self.stopped = True
76
+ self.server = None
77
+ if start: # pragma: no cover
78
+ self.start()
79
+
80
+ def _start_server(self):
81
+ from .namespace import NS
82
+
83
+ class Handler(RequestHandler):
84
+ source = self
85
+
86
+ def _loads(self, body):
87
+ """解析从web端口提交过来的数据.
88
+
89
+ 可能的数据有字符串和二进制,
90
+ 字符串可能是直接字符串,也可能是json编码后的字符串
91
+ 二进制可能是图像等直接可用的二进制,也可能是dill编码的二进制pyobject
92
+ """
93
+ try:
94
+ body = dill.loads(body)
95
+ except TypeError:
96
+ body = json.loads(body)
97
+ try:
98
+ body = pd.DataFrame.from_dict(body)
99
+ except:
100
+ body = body
101
+ except ValueError:
102
+ body = body.decode('utf-8')
103
+ finally:
104
+ return body
105
+
106
+ def _encode(self, body):
107
+ if isinstance(body, pd.DataFrame):
108
+ return body.sample(20).to_html()
109
+ else:
110
+ return json.dumps(body, ensure_ascii=False)
111
+
112
+ @gen.coroutine
113
+ def post(self):
114
+ body = dill.loads(self.request.body)
115
+ body = [self._loads(i) for i in body]
116
+ if not isinstance(body, list):
117
+ body = [body]
118
+
119
+ tag = unquote(self.request.headers['tag'])
120
+ print(tag)
121
+ if tag:
122
+ source = NS(tag)
123
+ if not source.is_cache:
124
+ source.start_cache(5, 64*64*24*5)
125
+ else:
126
+ source = self.source
127
+ for i in body:
128
+ yield source._emit(i)
129
+ self.write('OK')
130
+
131
+ @gen.coroutine
132
+ def get(self):
133
+ topic = unquote(self.request.path)
134
+ if topic == '/':
135
+ data = self.source.recent()
136
+ else:
137
+ stream = NS(topic.split('/')[1])
138
+ if not stream.is_cache:
139
+ stream.start_cache(10, 64*64*24*7)
140
+ data = stream.recent()
141
+ if 'deva' in self.request.headers['User-Agent']:
142
+ self.write(dill.dumps(data))
143
+ else:
144
+ for i in data:
145
+ self.write(self._encode(i)+'</br>')
146
+
147
+ self.application = Application([
148
+ (self.path, Handler),
149
+ ])
150
+ # self.server = HTTPServer(application, **self.server_kwargs)
151
+ self.server = self.application.listen(self.port)
152
+
153
+ def start(self):
154
+ if self.stopped:
155
+ self.stopped = False
156
+ self._start_server()
157
+ self.start_cache(5, 60*60*48)
158
+ # self.loop.add_callback(self._start_server)#这个会导致在端口占用情况下不报错
159
+
160
+ def stop(self):
161
+ """Shutdown HTTP server."""
162
+ if not self.stopped:
163
+ self.server.stop()
164
+ self.server = None
165
+ self.stopped = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deva
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: data eval in future
5
5
  Home-page: https://github.com/sostc/deva
6
6
  Author: spark
@@ -3,7 +3,7 @@ from os.path import exists
3
3
 
4
4
  setup(
5
5
  name='deva',
6
- version='1.2.3',
6
+ version='1.2.4',
7
7
  include_package_data=True,
8
8
  packages=find_packages(),
9
9
  python_requires='>=3.5',
deva-1.2.3/deva/topic.py DELETED
@@ -1,94 +0,0 @@
1
- from .core import Stream, sync
2
- from tornado import gen
3
- import aioredis
4
- import dill
5
- import logging
6
- import os
7
- import time
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
-
12
- @Stream.register_api(staticmethod)
13
- class RedisStream(Stream):
14
- """redis stream,read and write.
15
-
16
-
17
- 上游进来的写入redis ,redis的读出来的压入下游,
18
- exapmle::
19
-
20
- news = Stream.RedisStream('news')
21
- l = list()
22
- news>>l
23
- for i in range(1000):
24
- i>>news
25
-
26
- l|len
27
-
28
- """
29
-
30
- def __init__(self, topic, start=True,
31
- group=None, address='localhost', db=0, password=None, **kwargs):
32
- self.topic = topic
33
- self.redis_address = address
34
- self.redis_password = password
35
- self.group = group or hash(self)+hash(time.time())
36
- self.consumer = hash(self)
37
-
38
- super(RedisStream, self).__init__(ensure_io_loop=True, **kwargs)
39
- self.redis = None
40
- self.stopped = True
41
- if start:
42
- self.start()
43
-
44
- @gen.coroutine
45
- def process(self):
46
- if not self.redis:
47
- self.redis = yield aioredis.Redis(host=self.redis_address, password=self.redis_password)
48
-
49
- topic_exists = yield self.redis.exists(self.topic)
50
- if not topic_exists:
51
- print('create topic:', self.topic)
52
- yield self.redis.xadd(self.topic, {'data': dill.dumps('go')})
53
- try:
54
- yield self.redis.xgroup_create(self.topic, self.group)
55
- except Exception as e:
56
- print(e)
57
-
58
- while True:
59
- result = yield self.redis.xread(count=1, block=500, streams={self.topic: '$'})
60
- if result:
61
- data = dill.loads(result[0][1][0][1][b'data'])
62
- self._emit(data)
63
- if self.stopped:
64
- break
65
-
66
- @gen.coroutine
67
- def _send(self, data):
68
- if not self.redis:
69
- self.redis = yield aioredis.Redis(host=self.redis_address, password=self.redis_password)
70
- yield self.redis.xadd(self.topic, {'data': dill.dumps(data)})
71
-
72
- def emit(self, x, asynchronous=True):
73
- self.loop.add_callback(self._send, x)
74
- return x
75
-
76
- def start(self):
77
- if self.stopped:
78
- self.stopped = False
79
- self.loop.add_callback(self.process)
80
-
81
- def stop(self,):
82
- self.stopped = True
83
- self.loop.add_callback(self.redis.close)
84
-
85
-
86
- @Stream.register_api()
87
- class Topic(RedisStream):
88
-
89
- def __init__(self, name='', group=str(os.getpid()), maxsize=None, **kwargs):
90
- super().__init__(topic=name,
91
- group=group,
92
- start=True,
93
- name=name,
94
- **kwargs)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes