Skip to content

Commit a09a085

Browse files
committed
Drop Python2.7 and require Python3.6 or above
1 parent 69e18e2 commit a09a085

13 files changed

+44
-106
lines changed

.travis.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
language: python
22

33
python:
4-
- "2.7"
5-
- "3.5"
64
- "3.6"
5+
- "3.7"
6+
- "3.8"
7+
- "3.9"
78
os:
89
- linux
910

Readme.rst

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ The MeshCat architecture is based on the model used by Jupyter_:
2323
Installation
2424
------------
2525

26+
The latest version of MeshCat requires Python 3.6 or above.
27+
2628
Using pip:
2729

2830
::

setup.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
from setuptools import setup, find_packages
33

44
setup(name="meshcat",
5-
version="0.0.19",
5+
version="0.1.0",
66
description="WebGL-based visualizer for 3D geometries and scenes",
77
url="https://github.com/rdeits/meshcat-python",
8-
download_url="https://github.com/rdeits/meshcat-python/archive/v0.0.19.tar.gz",
8+
download_url="https://github.com/rdeits/meshcat-python/archive/v0.1.0.tar.gz",
99
author="Robin Deits",
1010
author_email="[email protected]",
1111
license="MIT",
@@ -20,10 +20,10 @@
2020
install_requires=[
2121
"ipython >= 5",
2222
"u-msgpack-python >= 2.4.1",
23-
"numpy >= 1.14.0" if sys.version_info >= (3, 0) else "numpy >= 1.14.0, < 1.17",
24-
"tornado >= 4.0.0" if sys.version_info >= (3, 0) else "tornado >= 4.0.0, < 6.0",
23+
"numpy >= 1.14.0",
24+
"tornado >= 4.0.0",
2525
"pyzmq >= 17.0.0",
26-
"pyngrok >= 4.1.6" if sys.version_info >= (3, 0) else "pyngrok >= 4.1.6, < 5.0.0"
26+
"pyngrok >= 4.1.6",
2727
],
2828
zip_safe=False,
2929
include_package_data=True

src/meshcat/animation.py

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
from __future__ import absolute_import, division, print_function
2-
31
import tempfile
42
import tarfile
5-
import sys
63
import os.path
74
import subprocess
8-
if sys.version_info >= (3, 0):
9-
unicode = str
105

116
import bisect
127
from . import transformations as tf
@@ -34,8 +29,8 @@ def set_property(self, frame, value):
3429

3530
def lower(self):
3631
return {
37-
u"name": unicode("." + self.name),
38-
u"type": unicode(self.jstype),
32+
u"name": str("." + self.name),
33+
u"type": str(self.jstype),
3934
u"keys": [{
4035
u"time": self.frames[i],
4136
u"value": self.values[i]
@@ -63,7 +58,7 @@ def set_property(self, frame, property, jstype, value):
6358
def lower(self):
6459
return {
6560
u"fps": self.fps,
66-
u"name": unicode(self.name),
61+
u"name": str(self.name),
6762
u"tracks": [t.lower() for t in self.tracks.values()]
6863
}
6964

src/meshcat/commands.py

-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
from __future__ import absolute_import, division, print_function
2-
3-
import sys
4-
if sys.version_info >= (3, 0):
5-
unicode = str
6-
71
from .geometry import Geometry, Object, Mesh, MeshPhongMaterial, OrthographicCamera, PointsMaterial, Points
82
from .path import Path
93

src/meshcat/geometry.py

+14-31
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
from __future__ import absolute_import, division, print_function
2-
3-
import sys
41
import base64
52
import uuid
6-
7-
if sys.version_info >= (3, 0):
8-
unicode = str
9-
from io import StringIO, BytesIO
10-
else:
11-
from StringIO import StringIO
12-
BytesIO = StringIO
13-
14-
3+
from io import StringIO, BytesIO
154
import umsgpack
165
import numpy as np
176

@@ -20,7 +9,7 @@
209

2110
class SceneElement(object):
2211
def __init__(self):
23-
self.uuid = unicode(uuid.uuid1())
12+
self.uuid = str(uuid.uuid1())
2413

2514

2615
class ReferenceSceneElement(SceneElement):
@@ -202,7 +191,7 @@ def from_file(fname):
202191
def lower(self, object_data):
203192
return {
204193
u"uuid": self.uuid,
205-
u"url": unicode("data:image/png;base64," + base64.b64encode(self.data).decode('ascii'))
194+
u"url": str("data:image/png;base64," + base64.b64encode(self.data).decode('ascii'))
206195
}
207196

208197

@@ -280,7 +269,7 @@ def __init__(self, left, right, top, bottom, near, far, zoom=1):
280269
self.near = near
281270
self.far = far
282271
self.zoom = zoom
283-
272+
284273
def lower(self):
285274
data = {
286275
u"object": {
@@ -332,15 +321,12 @@ def pack_numpy_array(x):
332321

333322

334323
def data_from_stream(stream):
335-
if sys.version_info >= (3, 0):
336-
if isinstance(stream, BytesIO):
337-
data = stream.read().decode(encoding='utf-8')
338-
elif isinstance(stream, StringIO):
339-
data = stream.read()
340-
else:
341-
raise ValueError('Stream must be instance of StringIO or BytesIO, not {}'.format(type(stream)))
342-
else:
324+
if isinstance(stream, BytesIO):
325+
data = stream.read().decode(encoding='utf-8')
326+
elif isinstance(stream, StringIO):
343327
data = stream.read()
328+
else:
329+
raise ValueError('Stream must be instance of StringIO or BytesIO, not {}'.format(type(stream)))
344330
return data
345331

346332

@@ -401,15 +387,12 @@ def from_file(fname):
401387

402388
@staticmethod
403389
def from_stream(f):
404-
if sys.version_info >= (3, 0):
405-
if isinstance(f, BytesIO):
406-
arr = np.frombuffer(f.read(), dtype=np.uint8)
407-
elif isinstance(f, StringIO):
408-
arr = np.frombuffer(bytes(f.read(), "utf-8"), dtype=np.uint8)
409-
else:
410-
raise ValueError('Stream must be instance of StringIO or BytesIO, not {}'.format(type(f)))
411-
else:
390+
if isinstance(f, BytesIO):
412391
arr = np.frombuffer(f.read(), dtype=np.uint8)
392+
elif isinstance(f, StringIO):
393+
arr = np.frombuffer(bytes(f.read(), "utf-8"), dtype=np.uint8)
394+
else:
395+
raise ValueError('Stream must be instance of StringIO or BytesIO, not {}'.format(type(f)))
413396
_, extcode = threejs_type(np.uint8)
414397
encoded = umsgpack.Ext(extcode, arr.tobytes())
415398
return MeshGeometry(encoded, u"stl")

src/meshcat/path.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
from __future__ import absolute_import, division, print_function
2-
3-
import sys
4-
if sys.version_info >= (3, 0):
5-
unicode = str
6-
7-
81
class Path(object):
92
__slots__ = ["entries"]
103

@@ -21,7 +14,7 @@ def append(self, other):
2114
return Path(new_path)
2215

2316
def lower(self):
24-
return unicode("/" + "/".join(self.entries))
17+
return "/" + "/".join(self.entries)
2518

2619
def __hash__(self):
2720
return hash(self.entries)

src/meshcat/servers/zmqserver.py

+14-28
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
import subprocess
99
import multiprocessing
1010

11-
if sys.version_info >= (3, 0):
12-
ADDRESS_IN_USE_ERROR = OSError
13-
else:
14-
import socket
15-
ADDRESS_IN_USE_ERROR = socket.error
16-
1711
import tornado.web
1812
import tornado.ioloop
1913
import tornado.websocket
@@ -43,7 +37,7 @@ def start_zmq_server_as_subprocess(zmq_url=None, server_args=[]):
4337
"""
4438
Starts the ZMQ server as a subprocess, passing *args through popen.
4539
Optional Keyword Arguments:
46-
zmq_url
40+
zmq_url
4741
"""
4842
# Need -u for unbuffered output: https://stackoverflow.com/a/25572491
4943
args = [sys.executable, "-u", "-m", "meshcat.servers.zmqserver"]
@@ -58,16 +52,13 @@ def start_zmq_server_as_subprocess(zmq_url=None, server_args=[]):
5852
# e.g. on Windows SYSTEMROOT and PATH
5953
env = dict(os.environ)
6054
env["PYTHONPATH"] = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
61-
kwargs = {
62-
'stdout': subprocess.PIPE,
63-
'stderr': subprocess.PIPE,
64-
'env': env
65-
}
6655
# Use start_new_session if it's available. Without it, in jupyter the server
6756
# goes down when we cancel execution of any cell in the notebook.
68-
if sys.version_info.major >= 3:
69-
kwargs['start_new_session'] = True
70-
server_proc = subprocess.Popen(args, **kwargs)
57+
server_proc = subprocess.Popen(args,
58+
stdout=subprocess.PIPE,
59+
stderr=subprocess.PIPE,
60+
env=env,
61+
start_new_session=True)
7162
line = ""
7263
while "zmq_url" not in line:
7364
line = server_proc.stdout.readline().strip().decode("utf-8")
@@ -117,7 +108,7 @@ def find_available_port(func, default_port, max_attempts=MAX_ATTEMPTS, **kwargs)
117108
port = default_port + i
118109
try:
119110
return func(port, **kwargs), port
120-
except (ADDRESS_IN_USE_ERROR, zmq.error.ZMQError):
111+
except (OSError, zmq.error.ZMQError):
121112
print("Port: {:d} in use, trying another...".format(port), file=sys.stderr)
122113
except Exception as e:
123114
print(type(e))
@@ -166,7 +157,7 @@ def set_extra_headers(self, path):
166157
class ZMQWebSocketBridge(object):
167158
context = zmq.Context()
168159

169-
def __init__(self, zmq_url=None, host="127.0.0.1", port=None,
160+
def __init__(self, zmq_url=None, host="127.0.0.1", port=None,
170161
certfile=None, keyfile=None, ngrok_http_tunnel=False):
171162
self.host = host
172163
self.websocket_pool = set()
@@ -214,19 +205,14 @@ def f(port):
214205
import pyngrok.conf
215206
import pyngrok.ngrok
216207

217-
kwargs = {}
218208
# Use start_new_session if it's available. Without it, in
219209
# jupyter the server goes down when we cancel execution of any
220210
# cell in the notebook.
221-
if sys.version_info.major >= 3:
222-
kwargs['start_new_session'] = True
223-
config = pyngrok.conf.PyngrokConfig(**kwargs)
211+
config = pyngrok.conf.PyngrokConfig(start_new_session=True)
224212
self.web_url = pyngrok.ngrok.connect(self.fileserver_port, "http", pyngrok_config=config)
225213

226214
# pyngrok >= 5.0.0 returns an NgrokTunnel object instead of the string.
227-
if sys.version_info.major < 3:
228-
self.web_url = self.web_url.decode("utf-8")
229-
elif not isinstance(self.web_url, str):
215+
if not isinstance(self.web_url, str):
230216
self.web_url = self.web_url.public_url
231217
self.web_url += "/static/"
232218

@@ -267,8 +253,8 @@ def handle_zmq(self, frames):
267253
path = list(filter(lambda x: len(x) > 0, frames[1].decode("utf-8").split("/")))
268254
data = frames[2]
269255
# Support caching of objects (note: even UUIDs have to match).
270-
cache_hit = (cmd == "set_object" and
271-
find_node(self.tree, path).object and
256+
cache_hit = (cmd == "set_object" and
257+
find_node(self.tree, path).object and
272258
find_node(self.tree, path).object == data)
273259
if not cache_hit:
274260
self.forward_to_websockets(frames)
@@ -379,8 +365,8 @@ def main():
379365
parser.add_argument('--open', '-o', action="store_true")
380366
parser.add_argument('--certfile', type=str, default=None)
381367
parser.add_argument('--keyfile', type=str, default=None)
382-
parser.add_argument('--ngrok_http_tunnel', action="store_true", help="""
383-
ngrok is a service for creating a public URL from your local machine, which
368+
parser.add_argument('--ngrok_http_tunnel', action="store_true", help="""
369+
ngrok is a service for creating a public URL from your local machine, which
384370
is very useful if you would like to make your meshcat server public.""")
385371
results = parser.parse_args()
386372
bridge = ZMQWebSocketBridge(zmq_url=results.zmq_url,

src/meshcat/tests/test_drawing.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
from __future__ import absolute_import, division, print_function
2-
31
import unittest
42
import subprocess
53
import sys
64
import tempfile
75
import os
86

9-
if sys.version_info >= (3, 0):
10-
from io import StringIO, BytesIO
11-
else:
12-
from StringIO import StringIO
13-
BytesIO = StringIO
7+
from io import StringIO, BytesIO
148

159
import io
1610

src/meshcat/tests/test_ports.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from __future__ import absolute_import, division, print_function
2-
31
import unittest
42
import os
53
import subprocess
@@ -11,7 +9,7 @@
119

1210
class TestPortScan(unittest.TestCase):
1311
"""
14-
Test that the ZMQ server can correctly handle its default ports
12+
Test that the ZMQ server can correctly handle its default ports
1513
already being in use.
1614
"""
1715

src/meshcat/tests/test_start_server.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from __future__ import absolute_import, division, print_function
2-
31
import unittest
42

53
from meshcat.servers.zmqserver import start_zmq_server_as_subprocess

src/meshcat/transformations.py

-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@
193193
194194
"""
195195

196-
from __future__ import absolute_import, division, print_function
197-
198196
import math
199197

200198
import numpy

src/meshcat/visualizer.py

-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
from __future__ import absolute_import, division, print_function
2-
3-
import sys
41
import webbrowser
5-
62
import umsgpack
73
import numpy as np
84
import zmq

0 commit comments

Comments
 (0)