diff --git a/doc/python/colorscales.md b/doc/python/colorscales.md index cc316249243..39c3fcdbb77 100644 --- a/doc/python/colorscales.md +++ b/doc/python/colorscales.md @@ -400,10 +400,10 @@ fig.show() ```python import plotly.graph_objects as go -import six.moves.urllib +import urllib import json -response = six.moves.urllib.request.urlopen( +response = urllib.request.urlopen( "https://raw.githubusercontent.com/plotly/datasets/master/custom_heatmap_colorscale.json" ) @@ -492,11 +492,11 @@ Like axes, you can customize the color bar ticks, labels, and values with `ticks ```python import plotly.graph_objects as go -import six.moves.urllib +import urllib import json # Load heatmap data -response = six.moves.urllib.request.urlopen( +response = urllib.request.urlopen( "https://raw.githubusercontent.com/plotly/datasets/master/custom_heatmap_colorscale.json") dataset = json.load(response) @@ -525,11 +525,11 @@ By default, color bars are displayed vertically. You can change a color bar to b ```python import plotly.graph_objects as go -import six.moves.urllib +import urllib import json # Load heatmap data -response = six.moves.urllib.request.urlopen( +response = urllib.request.urlopen( "https://raw.githubusercontent.com/plotly/datasets/master/custom_heatmap_colorscale.json") dataset = json.load(response) diff --git a/doc/python/graphing-multiple-chart-types.md b/doc/python/graphing-multiple-chart-types.md index e482015f4b9..881cd75cfe3 100644 --- a/doc/python/graphing-multiple-chart-types.md +++ b/doc/python/graphing-multiple-chart-types.md @@ -85,9 +85,9 @@ import plotly.graph_objects as go # Load data import json -import six.moves.urllib +import urllib -response = six.moves.urllib.request.urlopen( +response = urllib.request.urlopen( "https://raw.githubusercontent.com/plotly/datasets/master/steepest.json") data = json.load(response) diff --git a/packages/python/chart-studio/chart_studio/plotly/chunked_requests/chunked_request.py b/packages/python/chart-studio/chart_studio/plotly/chunked_requests/chunked_request.py index b32cdc66dd8..a6a669e018e 100644 --- a/packages/python/chart-studio/chart_studio/plotly/chunked_requests/chunked_request.py +++ b/packages/python/chart-studio/chart_studio/plotly/chunked_requests/chunked_request.py @@ -1,10 +1,10 @@ -import time -import six +import http.client import os import ssl +import time +from io import StringIO -from six.moves import http_client -from six.moves.urllib.parse import urlparse, unquote +from urllib.parse import urlparse, unquote from chart_studio.api import utils @@ -50,12 +50,12 @@ def write(self, data, reconnect_on=("", 200, 502)): # Reconnect depending on the status code. if (response == "" and "" in reconnect_on) or ( response - and isinstance(response, http_client.HTTPResponse) + and isinstance(response, http.client.HTTPResponse) and response.status in reconnect_on ): self._reconnect() - elif response and isinstance(response, http_client.HTTPResponse): + elif response and isinstance(response, http.client.HTTPResponse): # If an HTTPResponse was recieved then # make the users aware instead of # auto-reconnecting in case the @@ -85,7 +85,7 @@ def write(self, data, reconnect_on=("", 200, 502)): "{msglen}\r\n{msg}\r\n".format(msglen=msglen, msg=msg).encode("utf-8") ) self._conn.sock.setblocking(0) - except http_client.socket.error: + except http.client.socket.error: self._reconnect() self.write(data) @@ -152,11 +152,11 @@ def _connect(self): if proxy_server and proxy_port: if ssl_enabled: context = self._get_ssl_context() - self._conn = http_client.HTTPSConnection( + self._conn = http.client.HTTPSConnection( proxy_server, proxy_port, context=context ) else: - self._conn = http_client.HTTPConnection(proxy_server, proxy_port) + self._conn = http.client.HTTPConnection(proxy_server, proxy_port) tunnel_headers = None if proxy_auth: @@ -166,9 +166,9 @@ def _connect(self): else: if ssl_enabled: context = self._get_ssl_context() - self._conn = http_client.HTTPSConnection(server, port, context=context) + self._conn = http.client.HTTPSConnection(server, port, context=context) else: - self._conn = http_client.HTTPConnection(server, port) + self._conn = http.client.HTTPConnection(server, port) self._conn.putrequest("POST", self._url) self._conn.putheader("Transfer-Encoding", "chunked") @@ -179,14 +179,14 @@ def _connect(self): # Set blocking to False prevents recv # from blocking while waiting for a response. self._conn.sock.setblocking(False) - self._bytes = six.b("") + self._bytes = b"" self._reset_retries() time.sleep(0.5) def close(self): """Close the connection to server. - If available, return a http_client.HTTPResponse object. + If available, return a http.client.HTTPResponse object. Closing the connection involves sending the Transfer-Encoding terminating bytes. @@ -199,7 +199,7 @@ def close(self): # require an extra \r\n. try: self._conn.send("\r\n0\r\n\r\n".encode("utf-8")) - except http_client.socket.error: + except http.client.socket.error: # In case the socket has already been closed return "" @@ -219,28 +219,28 @@ def _getresponse(self): while True: try: _bytes = self._conn.sock.recv(1) - except http_client.socket.error: + except http.client.socket.error: # For error 54: Connection reset by peer # (and perhaps others) - return six.b("") - if _bytes == six.b(""): + return b"" + if _bytes == b"": break else: response += _bytes # Set recv to be non-blocking again self._conn.sock.setblocking(False) - # Convert the response string to a http_client.HTTPResponse + # Convert the response string to a http.client.HTTPResponse # object with a bit of a hack - if response != six.b(""): + if response != b"": # Taken from # http://pythonwise.blogspot.ca/2010/02/parse-http-response.html try: - response = http_client.HTTPResponse(_FakeSocket(response)) + response = http.client.HTTPResponse(_FakeSocket(response)) response.begin() except: # Bad headers ... etc. - response = six.b("") + response = b"" return response def _isconnected(self): @@ -268,10 +268,10 @@ def _isconnected(self): # 3 - Check if the server has returned any data. # If they have, then start to store the response # in _bytes. - self._bytes = six.b("") + self._bytes = b"" self._bytes = self._conn.sock.recv(1) return False - except http_client.socket.error as e: + except http.client.socket.error as e: # Check why recv failed # Windows machines are the error codes # that start with 1 @@ -320,7 +320,7 @@ def _reconnect(self): if not self._isconnected(): try: self._connect() - except http_client.socket.error as e: + except http.client.socket.error as e: # Attempt to reconnect if the connection was refused if e.errno == 61 or e.errno == 10061: # errno 61 is the "Connection Refused" error @@ -345,8 +345,8 @@ def _reset_retries(self): self._delay = 1 -class _FakeSocket(six.StringIO): - # Used to construct a http_client.HTTPResponse object +class _FakeSocket(StringIO): + # Used to construct a http.client.HTTPResponse object # from a string. # Thx to: http://pythonwise.blogspot.ca/2010/02/parse-http-response.html def makefile(self, *args, **kwargs): diff --git a/packages/python/chart-studio/chart_studio/plotly/plotly.py b/packages/python/chart-studio/chart_studio/plotly/plotly.py index 07e8d2e1f0d..1e6257ab995 100644 --- a/packages/python/chart-studio/chart_studio/plotly/plotly.py +++ b/packages/python/chart-studio/chart_studio/plotly/plotly.py @@ -21,11 +21,10 @@ import json import os import time +import urllib import warnings import webbrowser -import six -import six.moves import json as _json import _plotly_utils.utils @@ -513,8 +512,6 @@ def get_figure(file_owner_or_url, file_id=None, raw=False): fid = "{}:{}".format(file_owner, file_id) response = v2.plots.content(fid, inline_data=True) figure = response.json() - if six.PY2: - figure = byteify(figure) # Fix 'histogramx', 'histogramy', and 'bardir' stuff for index, entry in enumerate(figure["data"]): try: @@ -620,7 +617,7 @@ def get_streaming_specs(self): # If no scheme (https/https) is included in the streaming_url, the # host will be None. Use streaming_url in this case. - host = six.moves.urllib.parse.urlparse(streaming_url).hostname or streaming_url + host = urllib.parse.urlparse(streaming_url).hostname or streaming_url headers = {"Host": host, "plotly-streamtoken": self.stream_id} streaming_specs = { @@ -1380,7 +1377,7 @@ def parse_grid_id_args(grid, grid_url): else: supplied_arg_name = supplied_arg_names.pop() if supplied_arg_name == "grid_url": - path = six.moves.urllib.parse.urlparse(grid_url).path + path = urllib.parse.urlparse(grid_url).path file_owner, file_id = path.replace("/~", "").split("/")[0:2] return "{0}:{1}".format(file_owner, file_id) else: @@ -1392,7 +1389,7 @@ def add_share_key_to_url(plot_url, attempt=0): Check that share key is enabled and update url to include the secret key """ - urlsplit = six.moves.urllib.parse.urlparse(plot_url) + urlsplit = urllib.parse.urlparse(plot_url) username = urlsplit.path.split("/")[1].split("~")[1] idlocal = urlsplit.path.split("/")[2] fid = "{}:{}".format(username, idlocal) diff --git a/packages/python/chart-studio/chart_studio/session.py b/packages/python/chart-studio/chart_studio/session.py index 6dba5493911..9f7fccd04d2 100644 --- a/packages/python/chart-studio/chart_studio/session.py +++ b/packages/python/chart-studio/chart_studio/session.py @@ -9,39 +9,37 @@ import copy -import six - import _plotly_utils.exceptions _session = {"credentials": {}, "config": {}, "plot_options": {}} CREDENTIALS_KEYS = { - "username": six.string_types, - "api_key": six.string_types, - "proxy_username": six.string_types, - "proxy_password": six.string_types, + "username": str, + "api_key": str, + "proxy_username": str, + "proxy_password": str, "stream_ids": list, } CONFIG_KEYS = { - "plotly_domain": six.string_types, - "plotly_streaming_domain": six.string_types, - "plotly_api_domain": six.string_types, + "plotly_domain": str, + "plotly_streaming_domain": str, + "plotly_api_domain": str, "plotly_ssl_verification": bool, "plotly_proxy_authorization": bool, "world_readable": bool, "auto_open": bool, - "sharing": six.string_types, + "sharing": str, } PLOT_OPTIONS = { - "filename": six.string_types, - "fileopt": six.string_types, + "filename": str, + "fileopt": str, "validate": bool, "world_readable": bool, "auto_open": bool, - "sharing": six.string_types, + "sharing": str, } SHARING_OPTIONS = ["public", "private", "secret"] diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py index 429315c1d91..04816fed5d6 100644 --- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py +++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_figure/test_get_figure.py @@ -7,10 +7,6 @@ """ from __future__ import absolute_import -from unittest import skipIf - -import six - import _plotly_utils.exceptions from chart_studio import exceptions from chart_studio.plotly import plotly as py @@ -93,7 +89,6 @@ def test_get_figure_raw(self): class TestBytesVStrings(PlotlyTestCase): - @skipIf(six.PY2, "Decoding and missing escapes only seen in PY3") def test_proper_escaping(self): un = "PlotlyImageTest" ak = "786r5mecv0" diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py index 7dee479f560..02ef22ee655 100644 --- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py +++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_get_requests/test_get_requests.py @@ -8,7 +8,6 @@ import copy import requests -import six import json as _json from chart_studio.tests.utils import PlotlyTestCase @@ -34,10 +33,7 @@ def test_user_does_not_exist(self): hd["plotly-apikey"] = api_key resource = "/apigetfile/{0}/{1}/".format(file_owner, file_id) response = requests.get(server + resource, headers=hd) - if six.PY2: - content = _json.loads(response.content) - else: - content = _json.loads(response.content.decode("unicode_escape")) + content = _json.loads(response.content.decode("unicode_escape")) error_message = ( "Aw, snap! We don't have an account for {0}. Want to " "try again? Sign in is not case sensitive.".format(username) @@ -55,10 +51,7 @@ def test_file_does_not_exist(self): hd["plotly-apikey"] = api_key resource = "/apigetfile/{0}/{1}/".format(file_owner, file_id) response = requests.get(server + resource, headers=hd) - if six.PY2: - content = _json.loads(response.content) - else: - content = _json.loads(response.content.decode("unicode_escape")) + content = _json.loads(response.content.decode("unicode_escape")) error_message = ( "Aw, snap! It looks like this file does " "not exist. Want to try again?" ) @@ -91,10 +84,7 @@ def test_private_permission_defined(self): hd["plotly-apikey"] = api_key resource = "/apigetfile/{0}/{1}/".format(file_owner, file_id) response = requests.get(server + resource, headers=hd) - if six.PY2: - content = _json.loads(response.content) - else: - content = _json.loads(response.content.decode("unicode_escape")) + content = _json.loads(response.content.decode("unicode_escape")) self.assertEqual(response.status_code, 403) # Private File that is shared @@ -109,10 +99,7 @@ def test_missing_headers(self): hd = copy.copy(default_headers) del hd[header] response = requests.get(server + resource, headers=hd) - if six.PY2: - content = _json.loads(response.content) - else: - content = _json.loads(response.content.decode("unicode_escape")) + content = _json.loads(response.content.decode("unicode_escape")) self.assertEqual(response.status_code, 422) def test_valid_request(self): @@ -125,10 +112,7 @@ def test_valid_request(self): hd["plotly-apikey"] = api_key resource = "/apigetfile/{0}/{1}/".format(file_owner, file_id) response = requests.get(server + resource, headers=hd) - if six.PY2: - content = _json.loads(response.content) - else: - content = _json.loads(response.content.decode("unicode_escape")) + content = _json.loads(response.content.decode("unicode_escape")) self.assertEqual(response.status_code, 200) # content = _json.loads(res.content) # response_payload = content['payload'] diff --git a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py index 7336e365fc4..5f108b51551 100644 --- a/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py +++ b/packages/python/chart-studio/chart_studio/tests/test_plot_ly/test_plotly/test_plot.py @@ -7,8 +7,9 @@ """ from __future__ import absolute_import +import urllib + import requests -import six import sys import json as _json import warnings @@ -211,8 +212,8 @@ def test_private_plot_response_with_and_without_share_key(self): self.assertEqual(private_plot_response.status_code, 404) secret_plot_url = py.add_share_key_to_url(private_plot_url) - urlsplit = six.moves.urllib.parse.urlparse(secret_plot_url) - secret_plot_json_file = six.moves.urllib.parse.urljoin( + urlsplit = urllib.parse.urlparse(secret_plot_url) + secret_plot_json_file = urllib.parse.urljoin( urlsplit.geturl(), "?.json" + urlsplit.query ) secret_plot_response = requests.get(secret_plot_json_file) diff --git a/packages/python/chart-studio/chart_studio/tools.py b/packages/python/chart-studio/chart_studio/tools.py index c27dcb71252..90b63f6310b 100644 --- a/packages/python/chart-studio/chart_studio/tools.py +++ b/packages/python/chart-studio/chart_studio/tools.py @@ -9,9 +9,9 @@ """ from __future__ import absolute_import +import urllib import warnings -import six import copy from _plotly_utils import optional_imports @@ -102,13 +102,13 @@ def set_credentials_file( ) ensure_local_plotly_files() # make sure what's there is OK credentials = get_credentials_file() - if isinstance(username, six.string_types): + if isinstance(username, str): credentials["username"] = username - if isinstance(api_key, six.string_types): + if isinstance(api_key, str): credentials["api_key"] = api_key - if isinstance(proxy_username, six.string_types): + if isinstance(proxy_username, str): credentials["proxy_username"] = proxy_username - if isinstance(proxy_password, six.string_types): + if isinstance(proxy_password, str): credentials["proxy_password"] = proxy_password if isinstance(stream_ids, (list, tuple)): credentials["stream_ids"] = stream_ids @@ -173,23 +173,23 @@ def set_config_file( ) settings = get_config_file() - if isinstance(plotly_domain, six.string_types): + if isinstance(plotly_domain, str): settings["plotly_domain"] = plotly_domain elif plotly_domain is not None: raise TypeError("plotly_domain should be a string") - if isinstance(plotly_streaming_domain, six.string_types): + if isinstance(plotly_streaming_domain, str): settings["plotly_streaming_domain"] = plotly_streaming_domain elif plotly_streaming_domain is not None: raise TypeError("plotly_streaming_domain should be a string") - if isinstance(plotly_api_domain, six.string_types): + if isinstance(plotly_api_domain, str): settings["plotly_api_domain"] = plotly_api_domain elif plotly_api_domain is not None: raise TypeError("plotly_api_domain should be a string") - if isinstance(plotly_ssl_verification, (six.string_types, bool)): + if isinstance(plotly_ssl_verification, (str, bool)): settings["plotly_ssl_verification"] = plotly_ssl_verification elif plotly_ssl_verification is not None: raise TypeError("plotly_ssl_verification should be a boolean") - if isinstance(plotly_proxy_authorization, (six.string_types, bool)): + if isinstance(plotly_proxy_authorization, (str, bool)): settings["plotly_proxy_authorization"] = plotly_proxy_authorization elif plotly_proxy_authorization is not None: raise TypeError("plotly_proxy_authorization should be a boolean") @@ -208,7 +208,7 @@ def set_config_file( settings.pop("sharing") elif world_readable is not None: raise TypeError("Input should be a boolean") - if isinstance(sharing, six.string_types): + if isinstance(sharing, str): settings["sharing"] = sharing elif sharing is not None: raise TypeError("sharing should be a string") @@ -260,12 +260,12 @@ def _get_embed_url(file_owner_or_url, file_id=None): "\nRun help on this function for more information." "".format(url, plotly_rest_url) ) - urlsplit = six.moves.urllib.parse.urlparse(url) + urlsplit = urllib.parse.urlparse(url) file_owner = urlsplit.path.split("/")[1].split("~")[1] file_id = urlsplit.path.split("/")[2] # to check for share_key we check urlsplit.query - query_dict = six.moves.urllib.parse.parse_qs(urlsplit.query) + query_dict = urllib.parse.parse_qs(urlsplit.query) if query_dict: share_key = query_dict["share_key"][-1] else: diff --git a/packages/python/chart-studio/setup.py b/packages/python/chart-studio/setup.py index 556c8e144d6..5342b1fa97f 100644 --- a/packages/python/chart-studio/setup.py +++ b/packages/python/chart-studio/setup.py @@ -41,6 +41,6 @@ def readme(): "chart_studio.plotly.chunked_requests", "chart_studio.presentation_objs", ], - install_requires=["plotly", "requests", "retrying>=1.3.3", "six"], + install_requires=["plotly", "requests", "retrying>=1.3.3"], zip_safe=False, ) diff --git a/packages/python/chart-studio/test_requirements/requirements_37.txt b/packages/python/chart-studio/test_requirements/requirements_37.txt index b30b19ecb92..87fe133a487 100644 --- a/packages/python/chart-studio/test_requirements/requirements_37.txt +++ b/packages/python/chart-studio/test_requirements/requirements_37.txt @@ -1,7 +1,6 @@ decorator==4.0.9 nose==1.3.7 requests==2.12.4 -six==1.10.0 pytz==2016.10 retrying==1.3.3 pytest==3.5.1 diff --git a/packages/python/plotly/_plotly_utils/basevalidators.py b/packages/python/plotly/_plotly_utils/basevalidators.py index 3e22d546e46..98b9df2e5ae 100644 --- a/packages/python/plotly/_plotly_utils/basevalidators.py +++ b/packages/python/plotly/_plotly_utils/basevalidators.py @@ -10,7 +10,6 @@ from copy import deepcopy import re import sys -from six import string_types from _plotly_utils.optional_imports import get_module @@ -82,7 +81,7 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False): # ### Process kind ### if not kind: kind = () - elif isinstance(kind, string_types): + elif isinstance(kind, str): kind = (kind,) first_kind = kind[0] if kind else None @@ -457,13 +456,7 @@ def __init__( # ---------------------------- # Look for regular expressions for v in self.values: - if ( - v - and isinstance(v, string_types) - and v[0] == "/" - and v[-1] == "/" - and len(v) > 1 - ): + if v and isinstance(v, str) and v[0] == "/" and v[-1] == "/" and len(v) > 1: # String is a regex with leading and trailing '/' character regex_str = v[1:-1] self.val_regexs.append(re.compile(regex_str)) @@ -511,7 +504,7 @@ def perform_replacemenet(self, v): """ Return v with any applicable regex replacements applied """ - if isinstance(v, string_types): + if isinstance(v, str): for repl_args in self.regex_replacements: if repl_args: v = re.sub(repl_args[0], repl_args[1], v) @@ -584,7 +577,7 @@ def in_values(self, e): """ Return whether a value matches one of the enumeration options """ - is_str = isinstance(e, string_types) + is_str = isinstance(e, str) for v, regex in zip(self.values, self.val_regexs): if is_str and regex: in_values = fullmatch(regex, e) is not None @@ -671,7 +664,7 @@ def validate_coerce(self, v): if v is None: # Pass None through pass - elif isinstance(v, string_types): + elif isinstance(v, str): pass elif self.chart_studio and isinstance(v, self.chart_studio.grid_objs.Column): # Convert to id string @@ -983,7 +976,7 @@ def to_str_or_unicode_or_none(v): Convert a value to a string if it's not None, a string, or a unicode (on Python 2). """ - if v is None or isinstance(v, string_types): + if v is None or isinstance(v, str): return v else: return str(v) @@ -1049,7 +1042,7 @@ def validate_coerce(self, v): # If strict, make sure all elements are strings. if self.strict: - invalid_els = [e for e in v if not isinstance(e, string_types)] + invalid_els = [e for e in v if not isinstance(e, str)] if invalid_els: self.raise_invalid_elements(invalid_els) @@ -1091,10 +1084,10 @@ def validate_coerce(self, v): else: if self.strict: - if not isinstance(v, string_types): + if not isinstance(v, str): self.raise_invalid_val(v) else: - if isinstance(v, string_types): + if isinstance(v, str): pass elif isinstance(v, (int, float)): # Convert value to a string @@ -1433,7 +1426,7 @@ def perform_validate_coerce(v, allow_number=None): if isinstance(v, numbers.Number) and allow_number: # If allow_numbers then any number is ok return v - elif not isinstance(v, string_types): + elif not isinstance(v, str): # If not allow_numbers then value must be a string return None else: @@ -1596,7 +1589,7 @@ def validate_coerce(self, v): if v is None: v_valid = True - elif isinstance(v, string_types): + elif isinstance(v, str): v_lower = v.lower() if v_lower in self.named_colorscales: # Convert to color list @@ -1613,7 +1606,7 @@ def validate_coerce(self, v): elif is_array(v) and len(v) > 0: # If firset element is a string, treat as colorsequence - if isinstance(v[0], string_types): + if isinstance(v[0], str): invalid_els = [ e for e in v if ColorValidator.perform_validate_coerce(e) is None ] @@ -1633,7 +1626,7 @@ def validate_coerce(self, v): or len(e) != 2 or not isinstance(e[0], numbers.Number) or not (0 <= e[0] <= 1) - or not isinstance(e[1], string_types) + or not isinstance(e[1], str) or ColorValidator.perform_validate_coerce(e[1]) is None ) ] @@ -1655,7 +1648,7 @@ def present(self, v): # Return-type must be immutable if v is None: return None - elif isinstance(v, string_types): + elif isinstance(v, str): return v else: return tuple([tuple(e) for e in v]) @@ -1750,7 +1743,7 @@ def description(self): def validate_coerce(self, v): if v is None: pass - elif not isinstance(v, string_types): + elif not isinstance(v, str): self.raise_invalid_val(v) else: # match = re.fullmatch(self.regex, v) @@ -1842,7 +1835,7 @@ def description(self): return desc def vc_scalar(self, v): - if not isinstance(v, string_types): + if not isinstance(v, str): return None # To be generous we accept flags separated on plus ('+'), @@ -2363,7 +2356,7 @@ def description(self): def validate_coerce(self, v): if v is None: pass - elif isinstance(v, string_types): + elif isinstance(v, str): # Future possibilities: # - Detect filesystem system paths and convert to URI # - Validate either url or data uri @@ -2495,7 +2488,7 @@ def __init__(self, *args, **kwargs): super(TitleValidator, self).__init__(*args, **kwargs) def validate_coerce(self, v, skip_invalid=False): - if isinstance(v, string_types + (int, float)): + if isinstance(v, (str, int, float)): v = {"text": v} return super(TitleValidator, self).validate_coerce(v, skip_invalid=skip_invalid) @@ -2741,7 +2734,7 @@ def validate_coerce(self, v, skip_invalid=False): return copy.deepcopy(pio.templates[v]) # Otherwise, if v is a string, check to see if it consists of # multiple template names joined on '+' characters - elif isinstance(v, string_types): + elif isinstance(v, str): template_names = v.split("+") if all([name in pio.templates for name in template_names]): return pio.templates.merge_templates(*template_names) diff --git a/packages/python/plotly/_plotly_utils/colors/__init__.py b/packages/python/plotly/_plotly_utils/colors/__init__.py index 84943fe3940..06c0ff42a0b 100644 --- a/packages/python/plotly/_plotly_utils/colors/__init__.py +++ b/packages/python/plotly/_plotly_utils/colors/__init__.py @@ -77,7 +77,6 @@ import decimal from numbers import Number -import six from _plotly_utils import exceptions @@ -367,7 +366,7 @@ def validate_colors(colors, colortype="tuple"): ) colors[j] = each_color - if colortype == "rgb" and not isinstance(colors, six.string_types): + if colortype == "rgb" and not isinstance(colors, str): for j, each_color in enumerate(colors): rgb_color = color_parser(each_color, convert_to_RGB_255) colors[j] = color_parser(rgb_color, label_rgb) diff --git a/packages/python/plotly/_plotly_utils/tests/validators/test_string_validator.py b/packages/python/plotly/_plotly_utils/tests/validators/test_string_validator.py index 957b84c4361..380c5bccec9 100644 --- a/packages/python/plotly/_plotly_utils/tests/validators/test_string_validator.py +++ b/packages/python/plotly/_plotly_utils/tests/validators/test_string_validator.py @@ -1,5 +1,4 @@ import pytest -from six import string_types from _plotly_utils.basevalidators import StringValidator import numpy as np @@ -57,7 +56,7 @@ def validator_no_blanks_aok(): "val", ["bar", 234, np.nan, "HELLO!!!", "world!@#$%^&*()", "", "\u03BC"] ) def test_acceptance(val, validator): - expected = str(val) if not isinstance(val, string_types) else val + expected = str(val) if not isinstance(val, str) else val assert validator.validate_coerce(val) == expected diff --git a/packages/python/plotly/plotly/basedatatypes.py b/packages/python/plotly/plotly/basedatatypes.py index 1962a3e78a8..66cfb5520ee 100644 --- a/packages/python/plotly/plotly/basedatatypes.py +++ b/packages/python/plotly/plotly/basedatatypes.py @@ -3,8 +3,6 @@ import collections from collections import OrderedDict import re -import six -from six import string_types import warnings from contextlib import contextmanager from copy import deepcopy, copy @@ -1202,7 +1200,7 @@ def _selector_matches(obj, selector): return True # If selector is a string then put it at the 'type' key of a dictionary # to select objects where "type":selector - if isinstance(selector, six.string_types): + if isinstance(selector, str): selector = dict(type=selector) # If selector is a dict, compare the fields if isinstance(selector, dict) or isinstance(selector, BasePlotlyType): @@ -1224,7 +1222,7 @@ def _selector_matches(obj, selector): return False return True # If selector is a function, call it with the obj as the argument - elif six.callable(selector): + elif callable(selector): return selector(obj) else: raise TypeError( @@ -1825,7 +1823,7 @@ def _str_to_dict_path(key_path_str): tuple[str | int] """ if ( - isinstance(key_path_str, string_types) + isinstance(key_path_str, str) and "." not in key_path_str and "[" not in key_path_str and "_" not in key_path_str @@ -5764,7 +5762,7 @@ def _strip_subplot_suffix_of_1(self, prop): # ---------------------------------- # e.g. ('xaxis', 'range') or 'xaxis.range' prop_tuple = BaseFigure._str_to_dict_path(prop) - if len(prop_tuple) != 1 or not isinstance(prop_tuple[0], string_types): + if len(prop_tuple) != 1 or not isinstance(prop_tuple[0], str): return prop else: # Unwrap to scalar string @@ -5822,7 +5820,7 @@ def __setitem__(self, prop, value): # Convert prop to prop tuple # -------------------------- prop_tuple = BaseFigure._str_to_dict_path(prop) - if len(prop_tuple) != 1 or not isinstance(prop_tuple[0], string_types): + if len(prop_tuple) != 1 or not isinstance(prop_tuple[0], str): # Let parent handle non-scalar non-string cases super(BaseLayoutHierarchyType, self).__setitem__(prop, value) return @@ -5859,42 +5857,9 @@ def __dir__(self): Custom __dir__ that handles dynamic subplot properties """ # Include any active subplot values - if six.PY2: - - def get_attrs(obj): - import types - - if not hasattr(obj, "__dict__"): - return [] - if not isinstance(obj.__dict__, (dict, types.DictProxyType)): - raise TypeError("%s.__dict__ is not a dictionary" "" % obj.__name__) - return obj.__dict__.keys() - - def dir2(obj): - attrs = set() - if not hasattr(obj, "__bases__"): - # obj is an instance - if not hasattr(obj, "__class__"): - # slots - return sorted(get_attrs(obj)) - klass = obj.__class__ - attrs.update(get_attrs(klass)) - else: - # obj is a class - klass = obj - - for cls in klass.__bases__: - attrs.update(get_attrs(cls)) - attrs.update(dir2(cls)) - attrs.update(get_attrs(obj)) - return list(attrs) - - return dir2(self) + sorted(self._subplotid_props) - else: - - return list(super(BaseLayoutHierarchyType, self).__dir__()) + sorted( - self._subplotid_props - ) + return list(super(BaseLayoutHierarchyType, self).__dir__()) + sorted( + self._subplotid_props + ) class BaseTraceHierarchyType(BasePlotlyType): diff --git a/packages/python/plotly/plotly/figure_factory/_scatterplot.py b/packages/python/plotly/plotly/figure_factory/_scatterplot.py index d8724aa5ce1..097caaccae4 100644 --- a/packages/python/plotly/plotly/figure_factory/_scatterplot.py +++ b/packages/python/plotly/plotly/figure_factory/_scatterplot.py @@ -1,7 +1,5 @@ from __future__ import absolute_import -import six - from plotly import exceptions, optional_imports import plotly.colors as clrs from plotly.figure_factory import utils @@ -1045,11 +1043,7 @@ def create_scatterplotmatrix( # Validate colormap if isinstance(colormap, dict): colormap = clrs.validate_colors_dict(colormap, "rgb") - elif ( - isinstance(colormap, six.string_types) - and "rgb" not in colormap - and "#" not in colormap - ): + elif isinstance(colormap, str) and "rgb" not in colormap and "#" not in colormap: if colormap not in clrs.PLOTLY_SCALES.keys(): raise exceptions.PlotlyError( "If 'colormap' is a string, it must be the name " diff --git a/packages/python/plotly/plotly/figure_factory/utils.py b/packages/python/plotly/plotly/figure_factory/utils.py index d513f954a2e..9d501e12d78 100644 --- a/packages/python/plotly/plotly/figure_factory/utils.py +++ b/packages/python/plotly/plotly/figure_factory/utils.py @@ -1,7 +1,6 @@ from __future__ import absolute_import import decimal -import six from plotly import exceptions from plotly.colors import ( diff --git a/packages/python/plotly/plotly/io/_base_renderers.py b/packages/python/plotly/plotly/io/_base_renderers.py index 18d6ba18558..2142d1a7562 100644 --- a/packages/python/plotly/plotly/io/_base_renderers.py +++ b/packages/python/plotly/plotly/io/_base_renderers.py @@ -6,7 +6,6 @@ import os from os.path import isdir -import six from plotly import utils, optional_imports from plotly.io import to_json, to_image, write_image, write_html from plotly.io._orca import ensure_server @@ -666,7 +665,7 @@ def open_html_in_browser(html, using=None, new=0, autoraise=True): using, new, autoraise: See docstrings in webbrowser.get and webbrowser.open """ - if isinstance(html, six.string_types): + if isinstance(html, str): html = html.encode("utf8") browser = None diff --git a/packages/python/plotly/plotly/io/_html.py b/packages/python/plotly/plotly/io/_html.py index 3d1df5472c1..d4f5d094065 100644 --- a/packages/python/plotly/plotly/io/_html.py +++ b/packages/python/plotly/plotly/io/_html.py @@ -3,8 +3,6 @@ from pathlib import Path import webbrowser -import six - from _plotly_utils.optional_imports import get_module from plotly.io._utils import validate_coerce_fig_to_dict, plotly_cdn_url from plotly.offline.offline import _get_jconfig, get_plotlyjs @@ -255,7 +253,7 @@ def to_html( # ## Handle loading/initializing plotly.js ## include_plotlyjs_orig = include_plotlyjs - if isinstance(include_plotlyjs, six.string_types): + if isinstance(include_plotlyjs, str): include_plotlyjs = include_plotlyjs.lower() # Start/end of requirejs block (if any) @@ -287,9 +285,7 @@ def to_html( win_config=_window_plotly_config ) - elif isinstance(include_plotlyjs, six.string_types) and include_plotlyjs.endswith( - ".js" - ): + elif isinstance(include_plotlyjs, str) and include_plotlyjs.endswith(".js"): load_plotlyjs = """\ {win_config} \ @@ -307,7 +303,7 @@ def to_html( # ## Handle loading/initializing MathJax ## include_mathjax_orig = include_mathjax - if isinstance(include_mathjax, six.string_types): + if isinstance(include_mathjax, str): include_mathjax = include_mathjax.lower() mathjax_template = """\ @@ -323,9 +319,7 @@ def to_html( + _mathjax_config ) - elif isinstance(include_mathjax, six.string_types) and include_mathjax.endswith( - ".js" - ): + elif isinstance(include_mathjax, str) and include_mathjax.endswith(".js"): mathjax_script = ( mathjax_template.format(url=include_mathjax_orig) + _mathjax_config @@ -526,7 +520,7 @@ def write_html( ) # Check if file is a string - if isinstance(file, six.string_types): + if isinstance(file, str): # Use the standard pathlib constructor to make a pathlib object. path = Path(file) elif isinstance(file, Path): # PurePath is the most general pathlib object. diff --git a/packages/python/plotly/plotly/io/_json.py b/packages/python/plotly/plotly/io/_json.py index 0f047e3398b..ae9935b1dda 100644 --- a/packages/python/plotly/plotly/io/_json.py +++ b/packages/python/plotly/plotly/io/_json.py @@ -1,6 +1,5 @@ from __future__ import absolute_import -from six import string_types import json import decimal import datetime @@ -242,7 +241,7 @@ def write_json(fig, file, validate=True, pretty=False, remove_uids=True, engine= # Try to cast `file` as a pathlib object `path`. # ---------------------------------------------- - if isinstance(file, string_types): + if isinstance(file, str): # Use the standard Path constructor to make a pathlib object. path = Path(file) elif isinstance(file, Path): @@ -307,7 +306,7 @@ def from_json_plotly(value, engine=None): # Validate value # -------------- - if not isinstance(value, (string_types, bytes)): + if not isinstance(value, (str, bytes)): raise ValueError( """ from_json_plotly requires a string or bytes argument but received value of type {typ} @@ -430,8 +429,8 @@ def read_json(file, output_type="Figure", skip_invalid=False, engine=None): # Try to cast `file` as a pathlib object `path`. # ------------------------- # ---------------------------------------------- - file_is_str = isinstance(file, string_types) - if isinstance(file, string_types): + file_is_str = isinstance(file, str) + if isinstance(file, str): # Use the standard Path constructor to make a pathlib object. path = Path(file) elif isinstance(file, Path): @@ -461,7 +460,7 @@ def clean_to_json_compatible(obj, **kwargs): # Return immediately if we know we've hit a primitive value # Bail out fast for simple scalar types - if isinstance(obj, (int, float, string_types)): + if isinstance(obj, (int, float, str)): return obj if isinstance(obj, dict): diff --git a/packages/python/plotly/plotly/io/_kaleido.py b/packages/python/plotly/plotly/io/_kaleido.py index d7264bd06f6..51874c74631 100644 --- a/packages/python/plotly/plotly/io/_kaleido.py +++ b/packages/python/plotly/plotly/io/_kaleido.py @@ -1,5 +1,4 @@ from __future__ import absolute_import -from six import string_types import os import json from pathlib import Path @@ -231,7 +230,7 @@ def write_image( """ # Try to cast `file` as a pathlib object `path`. # ---------------------------------------------- - if isinstance(file, string_types): + if isinstance(file, str): # Use the standard Path constructor to make a pathlib object. path = Path(file) elif isinstance(file, Path): diff --git a/packages/python/plotly/plotly/io/_orca.py b/packages/python/plotly/plotly/io/_orca.py index 95835b839c6..475234c5545 100644 --- a/packages/python/plotly/plotly/io/_orca.py +++ b/packages/python/plotly/plotly/io/_orca.py @@ -13,7 +13,6 @@ from pathlib import Path import tenacity -from six import string_types import _plotly_utils.utils import plotly @@ -77,7 +76,7 @@ def validate_coerce_format(fmt): return None # Check format type - if not isinstance(fmt, string_types) or not fmt: + if not isinstance(fmt, str) or not fmt: raise_format_value_error(fmt) # Make lower case @@ -491,7 +490,7 @@ def executable(self, val): if val is None: self._props.pop("executable", None) else: - if not isinstance(val, string_types): + if not isinstance(val, str): raise ValueError( """ The executable property must be a string, but received value of type {typ}. @@ -499,7 +498,7 @@ def executable(self, val): typ=type(val), val=val ) ) - if isinstance(val, string_types): + if isinstance(val, str): val = [val] self._props["executable_list"] = val @@ -685,7 +684,7 @@ def topojson(self, val): if val is None: self._props.pop("topojson", None) else: - if not isinstance(val, string_types): + if not isinstance(val, str): raise ValueError( """ The topojson property must be a string, but received value of type {typ}. @@ -718,7 +717,7 @@ def mathjax(self, val): if val is None: self._props.pop("mathjax", None) else: - if not isinstance(val, string_types): + if not isinstance(val, str): raise ValueError( """ The mathjax property must be a string, but received value of type {typ}. @@ -748,7 +747,7 @@ def mapbox_access_token(self, val): if val is None: self._props.pop("mapbox_access_token", None) else: - if not isinstance(val, string_types): + if not isinstance(val, str): raise ValueError( """ The mapbox_access_token property must be a string, \ @@ -1746,7 +1745,7 @@ def write_image( # Try to cast `file` as a pathlib object `path`. # ---------------------------------------------- - if isinstance(file, string_types): + if isinstance(file, str): # Use the standard Path constructor to make a pathlib object. path = Path(file) elif isinstance(file, Path): diff --git a/packages/python/plotly/plotly/io/_renderers.py b/packages/python/plotly/plotly/io/_renderers.py index ce175589d25..feea2776a03 100644 --- a/packages/python/plotly/plotly/io/_renderers.py +++ b/packages/python/plotly/plotly/io/_renderers.py @@ -3,7 +3,6 @@ import textwrap from copy import copy -import six import os from distutils.version import LooseVersion @@ -211,7 +210,7 @@ def _validate_coerce_renderers(self, renderers_string): list of str """ # Validate value - if not isinstance(renderers_string, six.string_types): + if not isinstance(renderers_string, str): raise ValueError("Renderer must be specified as a string") renderer_names = renderers_string.split("+") diff --git a/packages/python/plotly/plotly/io/_templates.py b/packages/python/plotly/plotly/io/_templates.py index 2eb48bcdd01..800525b9508 100644 --- a/packages/python/plotly/plotly/io/_templates.py +++ b/packages/python/plotly/plotly/io/_templates.py @@ -8,8 +8,6 @@ import json from functools import reduce -from six import string_types - try: from math import gcd except ImportError: @@ -66,7 +64,7 @@ def __iter__(self): return iter(self._templates) def __getitem__(self, item): - if isinstance(item, string_types): + if isinstance(item, str): template_names = item.split("+") else: template_names = [item] diff --git a/packages/python/plotly/plotly/matplotlylib/renderer.py b/packages/python/plotly/plotly/matplotlylib/renderer.py index 0bfa2fe5576..147d50fe0a9 100644 --- a/packages/python/plotly/plotly/matplotlylib/renderer.py +++ b/packages/python/plotly/plotly/matplotlylib/renderer.py @@ -8,7 +8,6 @@ """ from __future__ import absolute_import -import six import warnings import plotly.graph_objs as go @@ -481,7 +480,7 @@ def draw_marked_line(self, **props): mode=mode, name=( str(props["label"]) - if isinstance(props["label"], six.string_types) + if isinstance(props["label"], str) else props["label"] ), x=[xy_pair[0] for xy_pair in props["data"]], @@ -712,7 +711,7 @@ def draw_text(self, **props): annotation = go.layout.Annotation( text=( str(props["text"]) - if isinstance(props["text"], six.string_types) + if isinstance(props["text"], str) else props["text"] ), opacity=props["style"]["alpha"], diff --git a/packages/python/plotly/plotly/tools.py b/packages/python/plotly/plotly/tools.py index 4560f13b030..feddc31cc23 100644 --- a/packages/python/plotly/plotly/tools.py +++ b/packages/python/plotly/plotly/tools.py @@ -12,7 +12,6 @@ import json import warnings -import six import re import os @@ -512,7 +511,7 @@ def _replace_newline(obj): for index, entry in enumerate(obj): l += [_replace_newline(entry)] return l - elif isinstance(obj, six.string_types): + elif isinstance(obj, str): s = obj.replace("\n", "
") if s != obj: warnings.warn( diff --git a/packages/python/plotly/recipe/meta.yaml b/packages/python/plotly/recipe/meta.yaml index 2c887106b18..701dfdd89bf 100644 --- a/packages/python/plotly/recipe/meta.yaml +++ b/packages/python/plotly/recipe/meta.yaml @@ -26,7 +26,6 @@ requirements: run: - python - tenacity >=6.2.0 - - six test: imports: diff --git a/packages/python/plotly/requirements.txt b/packages/python/plotly/requirements.txt index afe2545323d..2d763d4dae4 100644 --- a/packages/python/plotly/requirements.txt +++ b/packages/python/plotly/requirements.txt @@ -5,8 +5,5 @@ ### ### ################################################### -## python 2 to 3 compatibility ## -six>=1.15.0 - ## retrying requests ## tenacity>=6.2.0 diff --git a/packages/python/plotly/setup.py b/packages/python/plotly/setup.py index d8382df1c43..7ce054aab89 100644 --- a/packages/python/plotly/setup.py +++ b/packages/python/plotly/setup.py @@ -553,7 +553,7 @@ def run(self): data_files=[ ("etc/jupyter/nbconfig/notebook.d", ["jupyterlab-plotly.json"]), ], - install_requires=["tenacity>=6.2.0", "six"], + install_requires=["tenacity>=6.2.0"], zip_safe=False, cmdclass=dict( build_py=js_prerelease(versioneer_cmds["build_py"]), diff --git a/packages/python/plotly/test_requirements/requirements_36_core.txt b/packages/python/plotly/test_requirements/requirements_36_core.txt index 6265e5b540e..c5d8fc57034 100644 --- a/packages/python/plotly/test_requirements/requirements_36_core.txt +++ b/packages/python/plotly/test_requirements/requirements_36_core.txt @@ -1,4 +1,3 @@ requests==2.12.4 -six==1.10.0 tenacity==6.2.0 pytest==3.5.1 diff --git a/packages/python/plotly/test_requirements/requirements_36_optional.txt b/packages/python/plotly/test_requirements/requirements_36_optional.txt index 371b0a3cf6a..8c33824da66 100644 --- a/packages/python/plotly/test_requirements/requirements_36_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_36_optional.txt @@ -1,5 +1,4 @@ requests==2.12.4 -six==1.10.0 tenacity==6.2.0 pandas==0.24.2 numpy==1.19.5 diff --git a/packages/python/plotly/test_requirements/requirements_37_core.txt b/packages/python/plotly/test_requirements/requirements_37_core.txt index 6265e5b540e..c5d8fc57034 100644 --- a/packages/python/plotly/test_requirements/requirements_37_core.txt +++ b/packages/python/plotly/test_requirements/requirements_37_core.txt @@ -1,4 +1,3 @@ requests==2.12.4 -six==1.10.0 tenacity==6.2.0 pytest==3.5.1 diff --git a/packages/python/plotly/test_requirements/requirements_37_optional.txt b/packages/python/plotly/test_requirements/requirements_37_optional.txt index 371b0a3cf6a..8c33824da66 100644 --- a/packages/python/plotly/test_requirements/requirements_37_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_37_optional.txt @@ -1,5 +1,4 @@ requests==2.12.4 -six==1.10.0 tenacity==6.2.0 pandas==0.24.2 numpy==1.19.5 diff --git a/packages/python/plotly/test_requirements/requirements_38_core.txt b/packages/python/plotly/test_requirements/requirements_38_core.txt index 7f8c791a85e..edb622db5c0 100644 --- a/packages/python/plotly/test_requirements/requirements_38_core.txt +++ b/packages/python/plotly/test_requirements/requirements_38_core.txt @@ -1,4 +1,3 @@ requests==2.25.1 -six==1.15.0 tenacity==6.2.0 pytest==6.2.3 diff --git a/packages/python/plotly/test_requirements/requirements_38_optional.txt b/packages/python/plotly/test_requirements/requirements_38_optional.txt index 29e1c16a99a..411c9c0f158 100644 --- a/packages/python/plotly/test_requirements/requirements_38_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_38_optional.txt @@ -1,5 +1,4 @@ requests==2.25.1 -six==1.15.0 tenacity==6.2.0 pandas==1.2.4 numpy==1.20.2 diff --git a/packages/python/plotly/test_requirements/requirements_39_core.txt b/packages/python/plotly/test_requirements/requirements_39_core.txt index 7f8c791a85e..edb622db5c0 100644 --- a/packages/python/plotly/test_requirements/requirements_39_core.txt +++ b/packages/python/plotly/test_requirements/requirements_39_core.txt @@ -1,4 +1,3 @@ requests==2.25.1 -six==1.15.0 tenacity==6.2.0 pytest==6.2.3 diff --git a/packages/python/plotly/test_requirements/requirements_39_optional.txt b/packages/python/plotly/test_requirements/requirements_39_optional.txt index 29e1c16a99a..411c9c0f158 100644 --- a/packages/python/plotly/test_requirements/requirements_39_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_39_optional.txt @@ -1,5 +1,4 @@ requests==2.25.1 -six==1.15.0 tenacity==6.2.0 pandas==1.2.4 numpy==1.20.2