launch icon indicating copy to clipboard operation
launch copied to clipboard

Handle POSIX paths

Open hidmic opened this issue 5 years ago • 9 comments

Feature request

Feature description

A recent bugfix (https://github.com/ros2/launch_ros/pull/83) raised awareness about how we handle paths in launch. If launch actions and substitutions do not support POSIX paths but only native ones, platform-specific variations (e.g. slashes vs backslashes) creep all the way up to the launch file. At its worst, it makes XML -- and any other markup-based launch file -- platform-specific.

We should support POSIX paths across launch and encourage downstream packages' authors to maintain that support.

hidmic avatar Oct 11 '19 15:10 hidmic

cc @ivanpauno @wjwwood

hidmic avatar Oct 11 '19 15:10 hidmic

It's not clear to me exactly what needs to change, but we should just behave like CMake and Python, I think, and support POSIX everywhere and if the user happens to use the Windows style that may just not work on Linux. I believe it is the same in Python (on my mac):

>>> import os
>>> os.listdir('\tmp')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '\tmp'
>>> os.listdir('\\tmp')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '\\tmp'
>>> os.listdir('/tmp')
['com.apple.launchd.lw1JPx2qOm', 'com.apple.launchd.EPBR6r9RiP', 'powerlog', 'junk', 'com.apple.dyld', 'KSDownloadAction.XFstYUSm8v', '.dbfseventsd']

wjwwood avatar Oct 11 '19 18:10 wjwwood

Many actions make use of the os and os.path modules, and IIRC Python does not offer "universal paths" like it does for "universal newlines". Or I don't follow why pathlib and posixpath exist.

hidmic avatar Oct 11 '19 20:10 hidmic

Reading the docs, it sounds like if we use os.path it selects the module based on the platform:

posixpath for UNIX-style paths ntpath for Windows paths macpath for old-style MacOS paths

So, to resolve this ticket should we just ensure that we're using os.path everywhere?

jacobperron avatar Dec 04 '19 01:12 jacobperron

So, to resolve this ticket should we just ensure that we're using os.path everywhere?

I prefer using pathlib.Path.

I don't have a windows machine to try now, but I think that sometimes using os.path.join may cause problems when the input is a posix path (and not the os specific path).

Example:

user_posix_path_input = 'a/b/c/d'
something_that_may_be_wrong = os.path.join(user_posix_path_input, 'e')
print(something_that_may_be_wrong)

I'm not sure if the above code produce the desired result or not (IIRC, it produces something with mixed style path separator that later doesn't work when calling open, etc). But, I'm sure pathlib.Path does this job well:

user_posix_path_input = 'a/b/c/d'
something_that_is_ok = pathlib.Path(user_posix_path_input) / 'e'
print(str(something_that_is_ok))

I remember one test that was failing if I used a posix path on Windows: https://github.com/ros2/launch_ros/blob/master/test_launch_ros/test/test_launch_ros/frontend/test_node_frontend.py

I just used a os specific path, instead of a posix one, to correct the test. But launch files should accept both style (always accept posix style, also accept os specific style). I didn't check what was failing (if I did ... I don't remember).

ivanpauno avatar Dec 04 '19 13:12 ivanpauno

The spirit of this ticket was to enable a user to use POSIX paths throughout launch files and make that portable across platforms. To my surprise, in many cases you can throw pretty much any path at Windows and it'll work just fine, mixed slashes and backslashes included (just tried it). Even at the C level. It's inconsistent in this regard though e.g. command prompt commands won't accept slash separated paths.

So if we agree that the safest thing to do is to use OS specific style paths, we need to bridge the gap. And as @ivanpauno suggests, pathlib.Path will make sure we don't attempt to use POSIX paths within launch nor forward one of those to a launched process e.g. when passing parameter file paths to a node via command line arguments.

hidmic avatar Dec 04 '19 14:12 hidmic

Check here for a place where a path substitution is needed.

ivanpauno avatar Jan 30 '20 18:01 ivanpauno

Seems like we just need a Path substitution which will work much like PathJoinSubstitution, but using pathlib instead of os.path and a less verbose name. Also, launch stuffs expected to receive a path (e.g Command, PythonLaunchDescriptionSource) or return one (e.g FindPackageShare) could already internally use the Path substitution.

Is a pr for this desired?

caioaamaral avatar Mar 27 '21 22:03 caioaamaral

+1 to using pathlib . @caioaamaral a contribution would be most welcome!

hidmic avatar Mar 29 '21 19:03 hidmic