From 510e5a3ad6f7ebd85106e4a95df8c9c842aa6d57 Mon Sep 17 00:00:00 2001 From: Rasmus Scholer Date: Sun, 4 Oct 2015 18:16:51 -0400 Subject: [PATCH 1/2] Added websocket client and added python3 compatability. --- pygephi/__init__.py | 4 +-- pygephi/client.py | 45 ++++++++++++-------------- pygephi/websocket_client.py | 64 +++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 pygephi/websocket_client.py diff --git a/pygephi/__init__.py b/pygephi/__init__.py index 3168fa6..94f8a04 100644 --- a/pygephi/__init__.py +++ b/pygephi/__init__.py @@ -15,5 +15,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -from client import GephiClient, GephiFileHandler - +from __future__ import print_function, absolute_import +from .client import GephiClient, GephiFileHandler diff --git a/pygephi/client.py b/pygephi/client.py index 1b80993..dc1fcf1 100644 --- a/pygephi/client.py +++ b/pygephi/client.py @@ -19,26 +19,24 @@ Allow a Python script to communicate with Gephi using the Gephi Graph Streaming protocol and plugin. """ +from __future__ import print_function, absolute_import + __author__ = 'panisson@gmail.com' -import urllib2 try: - import json + import urllib2 except ImportError: - try: - import simplejson as json - except: - raise "Requires either simplejson or Python 2.6!" - + from urllib import request as urllib2 +import json import time class JSONClient(object): - + def __init__(self, autoflush=False, enable_timestamps=False, process_event_hook=None): self.data = "" self.autoflush = autoflush self.enable_timestamps = enable_timestamps - + if enable_timestamps: def default_peh(event): event['t'] = int(time.time()) @@ -49,56 +47,55 @@ def default_peh(event): self.peh = default_peh else: self.peh = lambda e: default_peh(process_event_hook(e)) - + def flush(self): if len(self.data) > 0: self._send(self.data) self.data = "" - + def _send(self, data): - print 'passing' - pass - + print('passing') + def add_node(self, id, flush=True, **attributes): self.data += json.dumps(self.peh({"an":{id:attributes}})) + '\r\n' if(self.autoflush): self.flush() - + def change_node(self, id, flush=True, **attributes): self.data += json.dumps(self.peh({"cn":{id:attributes}})) + '\r\n' if(self.autoflush): self.flush() - + def delete_node(self, id): self._send(json.dumps(self.peh({"dn":{id:{}}})) + '\r\n') - + def add_edge(self, id, source, target, directed=True, **attributes): attributes['source'] = source attributes['target'] = target attributes['directed'] = directed self.data += json.dumps(self.peh({"ae":{id:attributes}})) + '\r\n' if(self.autoflush): self.flush() - + def delete_edge(self, id): self._send(json.dumps(self.peh({"de":{id:{}}})) + '\r\n') - + def clean(self): self._send(json.dumps(self.peh({"dn":{"filter":"ALL"}})) + '\r\n') class GephiClient(JSONClient): - + def __init__(self, url='http://127.0.0.1:8080/workspace0', autoflush=False): JSONClient.__init__(self, autoflush) self.url = url - + def _send(self, data): conn = urllib2.urlopen(self.url+ '?operation=updateGraph', data) return conn.read() - + class GephiFileHandler(JSONClient): - + def __init__(self, out, **params): params['autoflush'] = True JSONClient.__init__(self, **params) self.out = out - + def _send(self, data): self.out.write(data) diff --git a/pygephi/websocket_client.py b/pygephi/websocket_client.py new file mode 100644 index 0000000..f747c0f --- /dev/null +++ b/pygephi/websocket_client.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# coding: utf-8 +# +# Copyright (C) 2012 André Panisson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Websocket communication with Gephi using the Gephi Graph-streaming protocol and plugin. + +Based on client.py by André Panisson and examples by Matthieu Totet + +See also: +* https://github.com/totetmatt/gephi.stream.graph.websocket +* http://matthieu-totet.fr/Koumin/2014/06/15/lets-play-gephi-streaming-api-the-hidden-websocket/ +* https://github.com/panisson/pygephi_graphstreaming/network + +""" + +from __future__ import print_function, absolute_import + +__author__ = 'rasmusscholer@gmail.com' + +import json +import time +from websocket import create_connection + +from .client import GephiClient + + +class GephiWsClient(GephiClient): + """ + Class for communicating with the Gephi graph-streaming plugin over websocket protocol. + This is slightly faster than REST communication with HTTP requests. + """ + def __init__(self, url='ws://127.0.0.1:8080/workspace0', autoflush=False, autoconnect=True): + GephiClient.__init__(self, url, autoflush) + self.conn = None + if autoconnect: + self.connect() + + def connect(self): + self.conn = create_connection(self.url) + + def _send(self, data): + if self.conn is None: + self.connect() + try: + return self.conn.send(data) + except ConnectionAbortedError as e: + print("Connection aborted,", e) + print("Retrying connection...") + self.connect() + self.conn.send(data) From eace8d34a43badb39922b7ee764bac453ecfadc7 Mon Sep 17 00:00:00 2001 From: Rasmus Scholer Date: Thu, 8 Oct 2015 18:31:07 -0400 Subject: [PATCH 2/2] Fixed better import and python3 compatability (urlopen takes bytes not str). --- pygephi/client.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pygephi/client.py b/pygephi/client.py index dc1fcf1..d57dc2c 100644 --- a/pygephi/client.py +++ b/pygephi/client.py @@ -24,11 +24,12 @@ __author__ = 'panisson@gmail.com' try: - import urllib2 + from urllib2 import urlopen except ImportError: - from urllib import request as urllib2 + from urllib.request import urlopen import json import time +import sys class JSONClient(object): @@ -54,7 +55,8 @@ def flush(self): self.data = "" def _send(self, data): - print('passing') + """ Overwrite in subclass. """ + pass def add_node(self, id, flush=True, **attributes): self.data += json.dumps(self.peh({"an":{id:attributes}})) + '\r\n' @@ -87,7 +89,10 @@ def __init__(self, url='http://127.0.0.1:8080/workspace0', autoflush=False): self.url = url def _send(self, data): - conn = urllib2.urlopen(self.url+ '?operation=updateGraph', data) + # For python3 we need to convert data string to bytes + if sys.version_info[0] > 2: + data = bytes(data, encoding='utf-8') + conn = urlopen(self.url+ '?operation=updateGraph', data) return conn.read() class GephiFileHandler(JSONClient):