-
-
Notifications
You must be signed in to change notification settings - Fork 403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Helper methods for updating options syntax #3188
Conversation
Here is the little script I am developing based on this ( from holoviews import opts
import pyparsing
while True:
string = input('> ')
try:
options = opts._completer_reprs(string)
except (SyntaxError, pyparsing.ParseException):
print('Parse error. Please try again')
continue
print('from holoviews import opts')
print(', '.join(options))
print('') It gives you the new import and the completer syntax to use/adapt appropriately. For instance, you can just copy the keywords out if you don't need to qualify by the element. python converter.py
> %%opts Bivariate [bandwidth=0.5] (cmap='Blues') Points [tools=['box_select']] (size=2)
from holoviews import opts
opts.Bivariate(bandwidth=0.5, cmap='Blues'), opts.Points(size=2, tools=['box_select']) |
And here is a script to run in import glob
import sys
import pyparsing
import holoviews as hv
from holoviews import opts, Cycle, Palette
from nbformat.current import read
try:
import pygments
except:
pygments = None
hv.extension('bokeh', 'matplotlib', 'plotly')
ns = {'Cycle':Cycle, 'Cycle, Palette':Palette}
for filename in sorted(glob.iglob('**/*.ipynb', recursive=True)):
if '.ipynb_checkpoints' in filename:
continue
with open(filename, 'r') as f:
nb = read(f, 'json')
for ws in nb.worksheets:
for cell in ws.cells:
if cell['cell_type'] == 'code':
if '%opts' in cell['input']:
for line in cell['input'].splitlines():
if '%opts' in line:
msg = '\n{filename}:\n {line}\n'
print(msg.format(filename=filename, line=line))
try:
options = opts._completer_reprs(line, ns=ns)
except (SyntaxError, pyparsing.ParseException):
print('Unexpected parse error')
code = '\n'.join(['from holoviews import opts',
', '.join(options)])
if pygments:
style = 'friendly'
term = pygments.formatters.Terminal256Formatter(style=style)
highlighted = pygments.highlight(code,
pygments.lexers.PythonLexer(),
term)
sys.stdout.write(highlighted)
else:
print(code)
while True:
string = input('\nContinue? ')
if string.strip() in ['y','Y', '']:
break |
e9e4a2f
to
19f8f16
Compare
@jbednar @philippjfr The purpose of this PR is to help make the doc update easier. After discussing a few things with Philipp, we decided the API still wasn't quite ready. In particular we decided we were unhappy with two things:
Commit c40069a address the first point by adding Commit 6985ab5 address the second point adding opts.defaults(opts.Curve(color='red')) Which I think is less mysterious, cleaner and offers tab-completion. I'm fairly happy with this though we will need to pick between 'warn', 'error' or leaving as it is and maybe consider whether this is a deprecation that can be managed via |
@philippjfr I have updated five of the bokeh gallery examples in f1654d7 in a way I propose should be idiomatic. I would like to check you agree with this style before I continue. |
As I work through these examples, I am trying to think of a style guide that describes the rules to apply. This doesn't have to be a style guide we recommend to users (though that would be nice) but it should at least be something we follow in our examples. Here is the provisional set of rules I am thinking of:
|
The "style guide" you laid out sounds good to me and roughly captures what we discussed yesterday. |
holoviews/util/__init__.py
Outdated
"although opts.defaults is the recommended approach.") | ||
|
||
if self._deprecate_magics_call == 'error': | ||
raise DeprecationWarning(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I should probably use DeprecationWarning
or PendingDeprecationWarning
in my deprecation PR as well.
OptsSpec.parse_options) or an %opts or %%opts magic string, | ||
return a list of corresponding completer reprs. The namespace is | ||
typically given as 'hv' if fully qualified namespaces are | ||
desired. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow the bit about the namespace, also having namespace
and ns
is confusing me here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Here ns
is the namespace as an actual namespace dictionary, e.g containing things like Cycle
or dim
that should be accepted by the parser (if a string is provided). And namespace
is the string as the prefix in the repr e.g if you don't want to import opts
from holoviews
but imported holoviews as hv
then you can use namespace='hv'
so the reprs are things like 'hv.opts.Curve(...)'
that can be executed as reprs.
The problem is that even after explaining it I can't think of better names! Maybe namespace
could be namespace_prefix
or prefix
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd vote for ns
to be ns_dict
or namespace_dict
, and namespace
to be namespace_str
or ns_str
. But I'm not sure how these objects will be used, so don't take my word for it...
I left one comment, otherwise this looks good to me. |
if self._deprecate_magics_call == 'error': | ||
raise DeprecationWarning(msg) | ||
elif self._deprecate_magics_call == 'warn': | ||
self.warning(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now wondering whether we should use warnings.warn(msg, DeprecationWarning)
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be a good idea as our param based warnings don't use warnings
. Happy to change it if you agree we should make this consistent throughout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested it and I get this horrible thing back:
/Users/philippjfr/miniconda/envs/anacondaviz/lib/python3.6/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Test
"""Entry point for launching an IPython kernel.
So let's not do that. My other preference would be for us to create a singleton Parameterized class in core/util.py which we can call Deprecation
or something, which we issue the deprecation warnings on.
f1654d7
to
67cc451
Compare
I added another rule to the 'guide' to capture something I discussed with Philipp:
So this: (density_grid * point_grid).options(opts.Bivariate(bandwidth=0.5, cmap='Blues'),
opts.Points(size=2, tools=['box_select'])) Should be: (density_grid * point_grid).options(
opts.Bivariate(bandwidth=0.5, cmap='Blues'),
opts.Points(size=2, tools=['box_select'])) And even though only one completer is used here: xticks = ("Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday")
heatmap.options(opts.HeatMap(radial=True, start_angle=np.pi*19/14, width=600, height=600,
yticks=None, xticks=xticks, xmarks=7, ymarks=3)) It should be: xticks = ("Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday")
heatmap.options(
opts.HeatMap(radial=True, start_angle=np.pi*19/14, width=600, height=600,
yticks=None, xticks=xticks, xmarks=7, ymarks=3)) |
And here is another rule which I think has five parts, three of which I think are optional and two that I think shouldn't be:
|
Unfortunately, following these rules means updating notebooks that might not even use any magics e.g abe3a09. |
@philippjfr Please review the changes in my last three commits to see if you agree with my changes. In particular, have a look at how I changed Note that I seem to have problems with links in general as I couldn't make |
Changes in the most recent commits look good, I think we have to think about a solution for both |
I like that change; seems clear.
I don't understand these objects. They seem to be replacements for magics, not actually magics, so I don't think they should have the word "magic" in their name. Can't you instead name them for what they are, even |
That is true and I am happy to rename them. But it is also true they don't really take line/cell magics as input (directly). Semantically it is something like |
16b4a7f
to
1bdf12f
Compare
@philippjfr 1bdf12f highlights a number of issues with this example:
I hope this is the trickiest example to update as it took a while! |
One other style to avoid. Instead of: grid.options('Scatter', tools=['hover', 'box_select'], fill_alpha=0.2, size=4) We should now use: grid.options(
opts.Scatter(tools=['hover', 'box_select'], fill_alpha=0.2, size=4)) |
Why? The first one seems like a very straightforward method call. |
I don't think we should disallow that style but for consistency in the examples I agree we should go with the latter approach. |
1bdf12f
to
d24819a
Compare
b47164b shows one valid exception to the rule in |
One note I want to make, the reprs of |
I've now updated all the notebooks in the bokeh gallery except for |
Discussing things with @philippjfr and @jbednar, there is another update to the style guide:
For example, you can use the template Note that this new rule actually subsumes the early exception around list/set/dict comprehensions. |
6b7ff39
to
db301fc
Compare
@philippjfr Rebased and updated the last notebook. I think it is ready for a final review/merge at which point I think I can cut a dev release. |
holoviews/tests/util/__init__.py
Outdated
@@ -121,9 +121,38 @@ def test_cell_opts_util_plot(self): | |||
def test_cell_opts_util_norm(self): | |||
mat1 = hv.Image(np.random.rand(5,5), name='mat1') | |||
self.assertEqual(mat1.id, None) | |||
opts("Image {+axiswise}", mat1) | |||
opts.cellmagic("Image {+axiswise}", mat1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bit confused by these, isn't this opts._cellmagic
now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess those tests weren't being run!
Okay fixed those tests and it's passing now, merging. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
This PR aims to offer a few useful tools that will make it easier to start using the new options syntax introduced in #3173. Currently the API is quite simple - see the unit tests for examples.