-
Notifications
You must be signed in to change notification settings - Fork 370
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
Fix of issue 246 - Make help and helpdesk more robust #688
Conversation
pynest/nest/lib/hl_api_helper.py
Outdated
iptnk = cfg['IPKernelApp']['parent_appname'] | ||
except NameError: | ||
iptnk = '' | ||
# test if jupyther notebook |
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.
Jupyter
pynest/nest/lib/hl_api_helper.py
Outdated
@@ -400,6 +404,124 @@ def broadcast(item, length, allowed_types, name="item"): | |||
return item | |||
|
|||
|
|||
def check_nb(): | |||
"""Check if is notebook or not | |||
""" |
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.
Maybe better
"""Return true if called from a Jupyter notebook."""
pynest/nest/lib/hl_api_helper.py
Outdated
iptnk = '' | ||
# test if jupyther notebook | ||
jpnk = re.findall(r'.*jupyter.*', os.environ['_']) | ||
ipjptk = re.findall(r'.*ipython.*', os.environ['_']) |
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.
When calling this from a plain ipython console, it returns a match (Python 2.7.12). So the function would return True also when called from the ipython console, not just from a notebook. Is that intentional?
pynest/nest/lib/hl_api_helper.py
Outdated
elif ipjptk: | ||
return True | ||
else: | ||
return False |
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.
You could simplify this to (but see comment above)
return iptnk == 'ipython-notebook' or re.search(r'ipython|jupyter', os.environ['_'])
pynest/nest/lib/hl_api_helper.py
Outdated
}); | ||
} | ||
); | ||
""" % (objname, hlptxt))) |
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.
%
substitution is deprecated in Python 3, .format()
should be used instead.
pynest/nest/lib/hl_api_helper.py
Outdated
return False | ||
|
||
|
||
def open_window(objname, hlptxt): |
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.
Maybe show_help_in_modal_window()
would be a better name? Should this be marked as private with a _
?
pynest/nest/lib/hl_api_helper.py
Outdated
""" % (objname, hlptxt))) | ||
|
||
|
||
def pdoc(hlpobj, pager): |
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.
Maybe call it show_help_with_pager()
would be a better name, and maybe also this one marked private?
@steffengraber I am testing now and here are some experiences:
if 'NEST_INSTALL_DIR' not in os.environ:
print('NEST help needs to know where NEST is installed. Please source nest_vars.sh or defined NEST_INSTALL_DIR manually.')
return
|
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.
Calling nest.helpdesk()
works fine at my workstation. When I call nest.help('iaf_psc_alpha')
or any NEST command I end up with the following error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../nest-fix246.install/lib64/python2.7/site-packages/nest/lib/hl_api_helper.py", line 234, in stack_checker_func
return f(*args, **kwargs)
File ".../nest-fix246.install/lib64/python2.7/site-packages/nest/lib/hl_api_info.py", line 90, in help
pdoc(hlpobj, pager)
File ".../nest-fix246.install/lib64/python2.7/site-packages/nest/lib/hl_api_helper.py", line 521, in pdoc
proc = subprocess.Popen([pager, objf])
File "/usr/lib64/python2.7/subprocess.py", line 709, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1326, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Am I using it wrong, is this related to something already mentioned by @heplesser or another bug?
@janhahne Sorry for the late response. |
@steffengraber I compiled nest with MPI on and my operating system is openSUSE 13.1. The problem still persist with your recent commits. Just to prevent any error on my side: |
@janhahne yes, nest.help('iaf_psc_alpha') is right. |
@steffengraber I am using python 2.7.6 and usually pynest works fine for me |
@janhahne with Python older than 2.7.8 the help generation did not work correctly. Is it possible for you to update and test ist again? |
@steffengraber I updated python to 2.7.13 and did a new clean build, but the error remains the same. I also noticed that if I enter any object that does not exist (as for example |
@janhahne Could you please try nest.help('iaf_psc_alpha', 'less'). |
@steffengraber |
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.
It works for me now---thanks! There are just a few little things to clean up, see detailed comments.
pynest/nest/lib/hl_api_info.py
Outdated
|
||
sr("/helpdesk << /command (%s) >> SetOptions" % browser) | ||
sr("helpdesk") | ||
url = os.path.join(os.environ['NEST_DOC_DIR'] + "/help", "helpindex.html") |
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.
Provide a useful error message if NEST_DOC_DIR
is undefined, similar as for missing NEST_INSTALL_DIR
.
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.
Here you mix os.path.join()
with string addition to build a URL. I think since we want a URL, we should not use os.path.join()
here.
pynest/nest/lib/hl_api_info.py
Outdated
sr("helpdesk") | ||
url = os.path.join(os.environ['NEST_DOC_DIR'] + "/help", "helpindex.html") | ||
if sys.platform[:3] == "win": | ||
os.startfile(url) |
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.
Why don't you use webbrowser
also under Windows?
pynest/nest/lib/hl_api_info.py
Outdated
if sys.platform[:3] == "win": | ||
os.startfile(url) | ||
if sys.platform[:3] == "dar": | ||
webbrowser.get('safari').open_new(url) |
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.
Why not webbrowser.open_new(url)
also here? Ok, due to this problem in OSX we need to ask for the browser explicitly under macOS are present (10.12.5). Worse, a failing webbrowser.open_new(url)
does not even raise a Python exception but returns happily. So I think we need to keep this, but i would be good to document why we do this.
pynest/nest/lib/hl_api_helper.py
Outdated
helpdir = os.path.join(os.environ['NEST_INSTALL_DIR'], "share", "doc", | ||
"nest", "help") | ||
objname = hlpobj + '.hlp' | ||
# @todo more pager |
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.
Isn't the pager list pretty complete?
pynest/nest/lib/hl_api_info.py
Outdated
browser : str, optional | ||
Name of the browser to use | ||
The system default browser. | ||
/helpdesk << /command (firefox) >> SetOptions in ~/.nestrc is now obsolete |
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 would drop this line of documentation, since it will confuse most users. The nestrc line is still relevant for the SLI level, so I'd leave it in nestrc.
@steffengraber PEP8 was still not entirely happy:
Otherwise, this looks fine to me. @janhahne Do you also explicitly approve? |
@heplesser
|
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 found a few more details ...
pynest/nest/lib/hl_api_helper.py
Outdated
pager = 'less' | ||
rc.close() | ||
|
||
# check if .netsrc exist |
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.
.nestrc
pynest/nest/lib/hl_api_helper.py
Outdated
rc.close() | ||
|
||
# check if .netsrc exist | ||
rc_file = os.environ['HOME'] + '/.nestrc' |
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.
You should use os.path.join(os.environ['HOME'], '.nestrc')
for portable path construction; applies in other places as well.
pynest/nest/lib/hl_api_helper.py
Outdated
rc_file = os.environ['HOME'] + '/.nestrc' | ||
if os.path.isfile(rc_file): | ||
# open ~/.nestrc | ||
rc = open(os.environ['HOME'] + '/.nestrc', 'r') |
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.
rc = open(rc_file, 'r')
pynest/nest/lib/hl_api_helper.py
Outdated
# open ~/.nestrc | ||
rc = open(os.environ['HOME'] + '/.nestrc', 'r') | ||
for line in rc: | ||
rctst = re.match(r'^\s?%', line) |
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.
Could you add a comment explaining/illustrating briefly what this RE looks for; that will make the code more maintainable. Applies also to other REs.
I think it would also be helpful if you could explain what this entire loop is trying to do---I cannot quite get it just from the code.
pynest/nest/lib/hl_api_info.py
Outdated
|
||
sr("/helpdesk << /command (%s) >> SetOptions" % browser) | ||
sr("helpdesk") | ||
url = os.path.join(os.environ['NEST_DOC_DIR'] + "/help", "helpindex.html") |
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.
Here you mix os.path.join()
with string addition to build a URL. I think since we want a URL, we should not use os.path.join()
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.
@steffengraber Thank you for addressing my issues! Now everything works as it should for me 👍
pynest/nest/lib/hl_api_helper.py
Outdated
subprocess.call([pager, objf]) | ||
fhlp.close() | ||
break | ||
if hlperror == True: |
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.
if hlperror
for tidier code and to make PEP8 happy.
@heplesser I added some documentation and PEP8 is happy now. |
Release notes: Improved help in PyNEST
|
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.
@steffengraber Thanks for the fixes, just two little details about path construction left to make it entirely pythonic and even windows-safe.
pynest/nest/lib/hl_api_info.py
Outdated
|
||
sr("/helpdesk << /command (%s) >> SetOptions" % browser) | ||
sr("helpdesk") | ||
url = os.path.join(os.environ['NEST_DOC_DIR'] + "/help", "helpindex.html") |
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 still have some issues with this line:
- This is not a URL, but the name of a local file to be opened by a browser, so the variable name should be
helpfile
or similar, noturl
. - Instead of mixing string concatenation and
os.path.join()
, just useos.path.join()
:
helpfile = os.path.join(os.environ['NEST_DOC_DIR'], 'help', 'helpindex.html')
pynest/nest/lib/hl_api_helper.py
Outdated
# reading ~/.nestrc lookink for pager to use. | ||
if pager is None: | ||
# check if .netsrc exist | ||
rc_file = os.environ['HOME'] + '/.nestrc' |
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.
This should be
rc_file = os.path.join(os.environ['HOME'], '.nestrc')
Minor Fix.
With this pull request, NEST uses only Python for the help system if you are on the Python level.
Therefore it doesn‘t matter if it is compiled with MPI or not.
In jupyter notebooks
nest.help(obj)
open a modal window with the help text.With
nest.help(obj, pager)
, you can open a texeditor like gedit from a notebook. If you use an terminaleditor (vi, nano, less, …) as pager, again the modal window open up.If you use
nest.helpdesk()
in a notebook a new tab is created.This pull request is a fix for issue #246.