8000 Allow style.use to open URLs · matplotlib/matplotlib@c8cc486 · GitHub
[go: up one dir, main page]

Skip to content

Commit c8cc486

Browse files
committed
Allow style.use to open URLs
1 parent d83a03c commit c8cc486

File tree

2 files changed

+53
-15
lines changed

2 files changed

+53
-15
lines changed

lib/matplotlib/__init__.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,16 @@ def _forward_ilshift(self, other):
155155
return self
156156
pyparsing.Forward.__ilshift__ = _forward_ilshift
157157

158-
import os, re, shutil, warnings
158+
try:
159+
from urllib.request import urlopen
160+
except ImportError:
161+
from urllib2 import urlopen
162+
163+
import os
164+
import re
165+
import tempfile
166+
import warnings
167+
import contextlib
159168
import distutils.sysconfig
160169

161170
# cbook must import matplotlib only within function
@@ -174,11 +183,8 @@ def _forward_ilshift(self, other):
174183
sys.argv = ['modpython']
175184

176185

177-
import sys, os, tempfile
178-
179186
from matplotlib.rcsetup import (defaultParams,
180-
validate_backend,
181-
validate_toolbar)
187+
validate_backend)
182188

183189
major, minor1, minor2, s, tmp = sys.version_info
184190
_python24 = (major == 2 and minor1 >= 4) or major >= 3
@@ -878,6 +884,25 @@ def rc_params(fail_on_error=False):
878884
return rc_params_from_file(fname, fail_on_error)
879885

880886

887+
URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\')
888+
889+
890+
def is_url(filename):
891+
"""Return True if string is an http or ftp path."""
892+
return URL_REGEX.match(filename) is not None
893+
894+
895+
@contextlib.contextmanager
896+
def _open_file_or_url(fname):
897+
if is_url(fname):
898+
f = urlopen(fname)
899+
yield f
900+
f.close()
901+
else:
902+
with open(fname) as f:
903+
yield f
904+
905+
881906
_error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
882907

883908

@@ -889,7 +914,7 @@ def rc_params_in_file(fname, fail_on_error=False):
889914
"""
890915
cnt = 0
891916
rc_temp = {}
892-
with open(fname) as fd:
917+
with _open_file_or_url(fname) as fd:
893918
for line in fd:
894919
cnt += 1
895920
strippedline = line.split('#', 1)[0].strip()

lib/matplotlib/style/core.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@
2323
BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
2424
# Users may want multiple library paths, so store a list of paths.
2525
USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
26-
STYLE_FILE_PATTERN = re.compile('([A-Za-z._-]+).style$')
26+
STYLE_FILE_PATTERN = re.compile('([\S]+).style$')
27+
28+
29+
def is_style_file(filename):
30+
"""Return True if the filename looks like a style file."""
31+
return STYLE_FILE_PATTERN.match(filename) is not None
2732

2833

2934
def use(name):
@@ -32,13 +37,23 @@ def use(name):
3237
Parameters
3338
----------
3439
name : str or list of str
35-
Name of style. For list of available styles see `style.available`.
36-
If given a list, each style is applied from first to last in the list.
40+
Name of style or path/URL to a style file. For a list of available
41+
style names, see `style.available`. If given a list, each style is
42+
applied from first to last in the list.
3743
"""
3844
if np.isscalar(name):
3945
name = [name]
40-
for s in name:
41-
plt.rcParams.update(library[s])
46+
47+
for style in name:
48+
if is_style_file(style):
49+
settings = mpl.rc_params_in_file(style)
50+
plt.rcParams.update(settings)
51+
elif style not in library:
52+
msg = ("'%s' not found in the style library. "
53+
"See `style.available` for list of available styles.")
54+
raise ValueError(msg % style)
55+
else:
56+
plt.rcParams.update(library[style])
4257

4358

4459
def load_base_library():
@@ -67,8 +82,8 @@ def iter_style_files(style_dir):
6782
"""Yield file path and name of styles in the given directory."""
6883
for path in os.listdir(style_dir):
6984
filename = os.path.basename(path)
70-
match = STYLE_FILE_PATTERN.match(filename)
71-
if match:
85+
if is_style_file(filename):
86+
match = STYLE_FILE_PATTERN.match(filename)
7287
path = os.path.abspath(os.path.join(style_dir, path))
7388
yield path, match.groups()[0]
7489

@@ -91,8 +106,6 @@ def update_nested_dict(main_dict, new_dict):
91106
# update named styles specified by user
92107
for name, rc_dict in new_dict.iteritems():
93108
if name in main_dict:
94-
# FIXME: This is currently broken because rc_params_from_file fills
95-
# in all settings so the update overwrites all values.
96109
main_dict[name].update(rc_dict)
97110
else:
98111
main_dict[name] = rc_dict

0 commit comments

Comments
 (0)
0