Physics extension #953

Closed
wants to merge 4 commits into
from

4 participants

@takluyver
IPython member

This is just adding an extension, so it shouldn't cause problems elsewhere. I've just done a pull request so others can have a glance over it if they're interested and suggest improvements. Otherwise, I'll merge it in a day or so.

Thanks to @birkenfeld for rewriting this code for IPython >= 0.11.

@fperez fperez commented on an outdated diff Oct 31, 2011
IPython/extensions/physics.py
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+"""
+IPython (0.11) extension for physical quantity input.
@fperez
IPython member
fperez added a line comment Oct 31, 2011

I'd remove that version number from here, it will just get stale pretty quickly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@fperez fperez commented on an outdated diff Oct 31, 2011
IPython/extensions/physics.py
+
+name = r'([_a-zA-Z]\w*)'
+number = r'(-?[\d0-9.eE]+)'
+unit = r'([a-zA-Z1][a-zA-Z0-9/*^-]*)'
+quantity = number + r'\s*' + unit
+
+inline_unit_re = re.compile(r'\((%s)\)' % quantity)
+slash_conv_re = re.compile(r'^(.*?)//\s*%s$' % unit)
+trailing_conv_re = re.compile(r'\s*//\s*%s$' % unit)
+nice_assign_re = re.compile(r'^%s\s*=\s*(%s)$' % (name, quantity))
+quantity_re = re.compile(quantity)
+subst_re = re.compile(r'\?' + name)
+
+def replace_inline(match):
+ return 'Q(\'' + match.group(1).replace('^', '**') + '\')'
+def replace_slash(match):
@fperez
IPython member
fperez added a line comment Oct 31, 2011

pep-8: two lines of whitespace between top-level definitions (function/class)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@fperez
IPython member

Minor suggestions, otherwise looks good.

@takluyver
IPython member

Done and done, compromising a bit on PEP-8 because those functions are clearly related, so one blank line feels nicer than two.

@fperez fperez commented on the diff Oct 31, 2011
IPython/extensions/physics.py
+ try:
+ val = raw_input('%s = ' % subst)
+ except EOFError:
+ sys.stdout.write('\n')
+ return
+ if not val:
+ return
+ if quantity_re.match(val):
+ val = '(' + val + ')'
+ expr = expr.replace('?' + subst, val)
+ if unit:
+ expr = '(' + expr + ').inUnitsOf("' + unit + '")'
+ shell.run_cell(expr, False)
+
+
+# monkey-patch a little
@fperez
IPython member
fperez added a line comment Oct 31, 2011

I'd put all the monkeypatching at the bottom so it stands out more clearly, in a clearly labeled section such as

#------------------------------------------------------------------------------
# Monkeypatching etc...
#------------------------------------------------------------------------------

That will separate declarations from code execution more clearly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@ellisonbg
IPython member

I am -1 on this being in IPython proper. The original module was added back when IPython was sort of a dumping ground for lots of things. I feel that in order for an extension to be shipped with IPython are couple of conditions should be satisfied:

  • They need to have broad appeal that a significant fraction of IPython users would want.
  • One of the core devs need to commit to their maint.
  • No dependencies or ones that are completely common. The Scientific package does not fall into this category in my mind.

Here is an alternate model for extensions that I think we should pursue and encourage:

  • Extensions are shipped with the packages they apply to. Thus the existing sympy extension should ship with sympy. A numpy extensions should ship with numpy, etc. The extension under review here should ship with Scientific.
  • We should improve our extensions loading API to make it easier to load extensions that are in other projects.

How does that sound?

@fperez
IPython member
@takluyver
IPython member

I agree in the general case, but I'd be inclined to include this one, because:

  • It has fairly broad appeal, particularly as a casual thing (i.e. potential users are less likely to put up with downloading and installing it separately)
  • It's not very complex, so it shouldn't be too much effort to maintain.
  • ScientificPython doesn't seem to be actively updated any more, so it's unlikely that it will ship as part of that in the near future. I don't know of any clear alternative package for what this uses. On the plus side, no updates means no API breakage from that side.

If we do want to leave it as a separate thing, Georg already has it in a bitbucket repo. But I really think it will be a lot more use if you can turn it on with one command. We should probably give a clear error message if Scientific isn't installed, though.

@ellisonbg
IPython member

If ScientificPython is not being maintained, that is even more reason to not include the extension in IPython. As Fernando said, someone should maintain it as a gist or on github/bitbucket and we can provide a link in our list of IPython extensions. I guess the bitbucket repo Georg has would work fine.

But we should open up a ticket to improve the extension loading syntax/API.

@fperez
IPython member

Despite the fact that I have a very soft spot for this extension, I think in this case Brian's conservative approach is wise: for one thing, we should have test coverage also for extensions, with an eye towards (in the hopefully not too distant future) having a buildbot. Having extensions that require somewhat exotic packages will make it that much harder to ensure that buildbots across platforms execute the full test suite (e.g., getting a windows buildbot with Scientific installed may or may not be trivial...).

An alternative approach would be to have an 'ipython-goodies' (perhaps with a better name) repo that we host, and that is independent from the main repo. For example on Debian/ubuntu, Emacs ships a simlar package with a ton of useful stuff on top of the core package.

Such a repo could contain more specialized extensions, extra magics and profiles, etc. Along with an easy command to do a user installation of the lot, I could see it being very useful. In the long run I would like upstream packages to adopt ipython extensions themselves, but I'm pretty sure there will always be useful, user-contributed things that upstream may (for whatever reason) decide not to package themselves. Such a repo would be a perfect area to maintain such tools and make them easily available to users; if upstream decides to adopt a tool we can always stop carrying it there, but if it doesn't adopt it our repo would provide it to users.

We'd have to think a little bit about the layout of such a repo, because ideally it should be possible for users to simply git clone it somewhere, and have IPython find things in there without requiring a separate manual re-installation every time they update via git pull. Basically we want to make it possible to have a workflow akin to what you get with setup.py develop or manual symlinking of a source tree.

@takluyver, how does this idea sound for the longer term? I think it's ultimately a more sustainable approach, and it also would be something where users would be more likely to contribute new tools that's easier than digging into the core. Basically, think of this as a version-controlled, installable repository of the best of the cookbook...

One caveat: if we go for this, I'd like to table the discussion for a bit so we can focus on closing the hard PRs and critical bugs we have left. I've been trying super hard to stay on top of new PRs, but if we keep putting out new features and ideas, we're never going to release 0.12 :)

@birkenfeld

Coming a bit late to the discussion; I won't shed too many tears if the extension isn't included in IPython itself, but the ScientificPython question can be answered quite easily: the module that's used from there is as good as standalone and has 800 lines, many of which are unit definitions; it could easily be put into the extension source. For me, this wouldn't be code duplication in the common sense because the original code isn't maintained anymore anyway. (It would also do away with the monkey-patching, and I could conceivable also make it a bit prettier.)

If the removal of the dependency is seen as a good thing, I'll do it and push to my bitbucket repo.

@takluyver
IPython member

OK, I can see I'm not going to get my way on this one. I'll withdraw the PR.

I think the best way forwards is to add an %install_ext magic, that will download a file and put it in the extensions directory. Then at least it's just two commands to start using this (%install_ext, %load_ext). We can keep other extensions in gists or whatever seems best. I guess this is the sort of thing to leave until after 0.12 now, though.

@birkenfeld: I made some changes here to drop the variables from the user namespace when the extension is unloaded. The relevant method isn't in 0.11, but once 0.12 is widespread, you might want to reuse the changes. (One upside of bundling it: we know what IPython version we're targeting)

@takluyver takluyver closed this Oct 31, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment