Merge lp://staging/~mikemc/dirspec/add-exefind into lp://staging/dirspec

Proposed by Mike McCracken
Status: Merged
Merged at revision: 8
Proposed branch: lp://staging/~mikemc/dirspec/add-exefind
Merge into: lp://staging/dirspec
Diff against target: 257 lines (+215/-1)
2 files modified
dirspec/tests/test_utils.py (+141/-1)
dirspec/utils.py (+74/-0)
To merge this branch: bzr merge lp://staging/~mikemc/dirspec/add-exefind
Reviewer Review Type Date Requested Status
dobey (community) Needs Fixing
Review via email: mp+113782@code.staging.launchpad.net

Commit message

- Add function for getting executable command lines across projects and platforms and packagings (LP: #1021833)

Description of the change

- Add function for getting executable command lines across projects and platforms and packagings (LP: #1021833)

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

First thing I notice this will need is an __all__ to only export the public method.

Also, I don't like the naming, and I think we should probably have a better fallback for Linux/BSD/etc… We'll also need to deal with varying python executable name, such as python3 instead of python.

review: Needs Fixing
9. By Mike McCracken

Add support for installed linux using generated-at-install module.constants to find BIN_DIR
Avoid using 'python ' + exe on non-mac/win
Refactor tests.

Revision history for this message
Mike McCracken (mikemc) wrote :

rev 9 addresses the __all__ attr, and the issue of a linux fallback.

On linux, the difference between installed and not installed is not the sys.frozen attribute.
I've adapted the approach from ubuntu_sso.utils.get_bin_dir:
On linux, if we are running from source, we find the path relative to the module, eg. srctree/bin next to srctree/ubuntu_sso. If there's something there, we use it, otherwise we look at the generated constants.py that is generated when setup.py is run.

Clients of this code other than ubuntu-sso-client would need to add a constants.py with a BIN_DIR attribute to work the same way. However, only sso-client currently launches any processes using Popen on linux - the other projects use DBus.

I am still open to suggestions about what to do wrt. the python exe name - I don't completely understand when & why that'll change.

Revision history for this message
Mike McCracken (mikemc) wrote :

Also, please elaborate on your naming concerns. I'm open to suggestions!

10. By Mike McCracken

Remove an unused line

Revision history for this message
dobey (dobey) wrote :

I don't like the name, because it's platform-specific, as there are no .exes on OSX or Linux generally (C# and things under WINE, notwithstanding). Also, dirspec already has a utils.py module, and this is but a utility function, albeit with a few additional private helper functions.

Also, I'm really not liking the API, now that I've thought about it more. The idea of having a special module in one's code that gets passed in, and must have specific platform-dependent constants in it, is rather nasty. I think all these things the code is poking at a module for, would be better passed in as kwargs on the entry point method.

As for the python prefix issue, we can't just prepend it anyway. It won't work very well for things which aren't written in Python. If someone else wanted to use the library in their code to launch a non-python application, for whatever reason, prefixing python here would break that. So I'd rather avoid us having that here if possible. It would be nice if we could find some other way to solve this problem for running programs from tree, on Windows/OS X. Maybe I don't understand that problem fully enough yet, and need to have it explained better to me, but it seems like a separate problem from the need to avoid duplicating the code to find the files on disk to run.

Revision history for this message
Mike McCracken (mikemc) wrote :

naming - no prob moving it to utils. call it utils.get_cmdline

originally wanted an API as smart as possible, otherwise we're not removing much complexity from the callsites.
But I don't disagree with the comments about the module pokery. It's
not a very intuitive API.

So, here's what it'd look like if we avoided module pokery:

We need to tell it the name of the executable we're looking for, and
three extra things:

- what directory to look in , or near (best we can do is pass in
       __file__ from something)
-- Unless we give it more info, like I was by passing the module, all
   it can do is look for a bin/ in cwd, then cwd/.. , etc...

- only for darwin: what the name of the sub-app will be if packaged.

- only for linux: we need to give it a way to get the compiled-in
  BIN_DIR constant for SSO, which is at ubuntu_sso.constants.BIN_DIR

Giving all this explicitly (and we always need to give all the args,
because the same code should work on all platforms) makes a kind of
messy call site:

cmdline = get_cmdline('ubuntuone-syncdaemon',
  ubuntuone.syncdaemon.__file__,
  "Ubuntu One Syncdaemon.app") # no constants module

cmdline = get_cmdline('ubuntu-sso-login-qt,
  ubuntu_sso.__file__,
  "Ubuntu SSO.app", # or, probably DARWIN_APP_NAMES['ubuntu-sso-login-qt']
  dir_constants=ubuntu_sso.constants)

# here's what the function's signature would look like, with some overly descriptive names that I didn't think about too hard:

def get_cmdline(executable_name, some_path_in_same_project_tree, darwin_subapp_name, linux_installed_constants_module=None)

Revision history for this message
Mike McCracken (mikemc) wrote :

Regarding prepending 'python ', the issue is that the scripts now have
an absolute path to /usr/bin/python, but on windows and darwin we have
a buildout-generated python wrapper that sets up PYTHONPATH to point
to the eggs in the buildout directory, etc, so we need to use that.

One option would be to avoid using the buildout python, and either
just set PYTHONPATH to include all the eggs while developing, or use
virtualenv, or something. However, that's a rather big change.

If we want to stick with the buildout python, we need to just prepend
'python' to the cmdline and use Popen(shell=True).

All that said, I think it'd be fine to move that out of this general
library function. There'd just be a bit of extra code after we call it
each time:

cmdline = get_cmdline(blah)
if getattr(sys, "frozen", None) is None and
   sys.platform in ('win32','darwin'):
   # then we are in a source tree, using the buildout python wrapper,
   # and we need to make sure we run it using that, so that its path
   # makes sense.
   cmdline = 'python ' + cmdline

for ease of writing tests, we might also want to wrap that in a
function on the client end (ie, not in dirspec)

11. By Mike McCracken

- Move get_cmdline into utils.py

- Don't prepend 'python ' to cmdline, this is too specific to buildout
  python and should be done by clients of this code.

Revision history for this message
dobey (dobey) wrote :

So, for the case where all the arguments are passed in, the API doesn't have to be overly complex to allow for it. We can simply require them to be passed in **kwargs, and document what they are called. This can keep the basic API nice and simple, and we can have additional things for the cases where we need them.

Revision history for this message
dobey (dobey) wrote :

This is more what I was thinking, in terms of having a 'smarter' API, that we could just use via kwargs, and simply state in the docstring what kwargs are available for use, though they aren't required: http://bazaar.launchpad.net/~dobey/dirspec/add-exefind/revision/12

I haven't updated the docstring in that revision, but there are the fallback_dirs= and app_names= kwargs, to specify a list of fallback directories, and a dict of app names for darwin.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches