Tips for coding python scripts / plugins compatible with Linux, Mac, Windows AND Xbox
#1
Exclamation 
Hi Guys,

I am developing (at least trying Big Grin) XBMC scripts with a French community of users using XBMC some on Linux and some on XBOX (and recently some on windows).
We went few time through the problem of having python script for XBMC NOT compatible for both Linux/Mac and XBOX/Windows.

Hopefully we have found a solution which should be compatible with all the platforms: Linux/Mac and XBOX/Windows
I don't know it has been already a topic on this subject, so sorry if I repeat something but it is better to give this information again since it could be very useful for XBMC Script developers.

The main problem between the 2 platforms Linux/Mac and XBOX/windows is:
  • the format of the path,
  • certain os command does NOT return the same result depending on the OS


Here is an example of code to add to your script in order to find the current path of your script:
Code:
############################################################################
# Get current working directory and update internal vars with it  
############################################################################

# Set paths
if os.name=='posix':
    # Linux case
    ROOTDIR = os.path.abspath(os.curdir).replace(';','')
else:
    # Xbox and Windows case
    ROOTDIR = os.getcwd().replace(';','')

IMAGEDIR    = os.path.join(ROOTDIR, "images")
CACHEDIR    = os.path.join(ROOTDIR, "cache")
DOWNLOADDIR = os.path.join(ROOTDIR, "download")

The other important thing is to only use the 'os.path.join' command instead of a combination of '+' and the os separtor '/' or '\\'.
And if you need to use this separator, it is better to use 'os.sep' instead.

Now an example of code of how to use those paths in order to remain compatible with all the platforms:
Code:
os.remove(os.path.join(DOWNLOADDIR, filename))

Those examples have been tested and work on both Linux/Xbox platforms.

I hope it will help. If every XBMC script developer could do script compatible script between platform it would be nice for the end user.
Right now we can see the issue with Linux users who try to use some script and it doesn't work because of issue on the format of the path used in the script, my guess is it is the same for Mac user too, and it would be a shame not to fix that on new scripts :o.

If you have a better way of writing thos code, please feel free to share with us. Thanks Big Grin
Reply
#2
Lightbulb 
Temhil Wrote:The main problem between the 2 platforms Linux/Mac and XBOX/windows is:
  • the format of the path,
  • certain os command does NOT return the same result depending on the OS
would it not be best to try to get those two root causes fixed in XBMC instead of working around them? Huh
...I am not sure if they should be classified as bugs or feature request but please submit new tickets on trac
http://trac.xbmc.org
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#3
os.getcwd() should return the same thing (i.e. no ; at the end) nowadays.
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


Image
Reply
#4
I fully agree with you Gamester17 it should be the same whatever the OS is, so for time being at least script can run on all platform with this workaround.
Nevertheless, even if that will be fix, developer of script will need to use command as os.join and os.sep instead of writing in the code something like:
Code:
filepath=ROOTDIR + '/' + filename

@Gamester17 - I am not familiar with ticket, how do you file it?

@jmarshall, exactly, that was the command I was talking about - one of the biggest problem is os.getcwd() does not return the same thing. For the format of the path if developer only use os.join and os.sep, it is OK, but with the issue on os.getcwd() for Linux case, we are not able to get the current directory properly.
Reply
#5
Please produce a simple example script that fails to return the correct result from os.getcwd().

Tickets are at http://trac.xbmc.org (login is your forum login).

Cheers
Jonathan
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


Image
Reply
#6
Trac is our tracking-system for tracking feature requests, bug reports, and code patches that is submitted to us.
http://trac.xbmc.org

Again I am not sure if your specific concern should be classified as a bug or a feature request but set it as a bug for now.

HOW-TO submit a feature request:
http://wiki.xbmc.org/?title=What_is_XBMC...to_XBMC.3F

HOW-TO submit a bug report:
http://wiki.xbmc.org/?title=HOW-TO_Submi...Bug_Report

HOW-TO submit a code patch:
http://wiki.xbmc.org/?title=HOW-TO_submit_a_patch

Wink
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#7
os.path.join should always be used to avoid errors.

os.getcwd() should to my knowledge return correct paths on xbox, linux, windows (can't test mac, since i dont own one *yet*)
Reply
#8
thanks for the info on ROOTDIR and I'll be changing all my code to use os.path.join as I update them for Atlantis scripting changes.

quick question, is this:
p = os.path.join('Q:','scripts',__scriptname__)

the same as

p = 'Q:\\scripts\\' + __scriptname__

in that its still from the Q: root ?
thanks
Retired from Add-on dev
Reply
#9
BigBellyBilly Wrote:thanks for the info on ROOTDIR and I'll be changing all my code to use os.path.join as I update them for Atlantis scripting changes.

quick question, is this:
p = os.path.join('Q:','scripts',__scriptname__)

the same as

p = 'Q:\\scripts\\' + __scriptname__

in that its still from the Q: root ?
thanks

I didn't try os.path.join with more than 2 arguments, but according to the documentation, what you wrote is correct and does what you said, here is what doc says:
join( path1[, path2[, ...]])
Join one or more path components intelligently. If any component is an absolute path, all previous components (on Windows, including the previous drive letter, if there was one) are thrown away, and joining continues. The return value is the concatenation of path1, and optionally path2, etc., with exactly one directory separator (os.sep) inserted between components, unless path2 is empty. Note that on Windows, since there is a current directory for each drive, os.path.join("c:", "foo") represents a path relative to the current directory on drive C: (c:foo), not c:\\foo.

Other than that sorry I didn't opened an ticket yet since I don't have ogs for Linux (I don't have currently Linux PC)
Reply
#10
yeah, I know you could have multiple params, but it was 'from root' I was unsure about.
But after some testing, I've found that its best to also use the os.sep

to get -> T:\script_data\myscriptname

use -> p = os.path.join('T:'+os.sep,'script_data',__scriptname__)

works on xbox , windows port. I'm assuming ok on linux
cheers
BBB
Retired from Add-on dev
Reply
#11
Thumbs Up 
Hi guys,

Sorry for coming back only now but since I don't have Linux box I wasn't able to generate logs for opening a bug.

Good news!
With MAC OS port I tried it and now it seems this issue has beem solved in XBMC Beta1 (probably before).
So now instead of doing a test on the OS, it just takes one line of code:
Code:
ROOTDIR = xbmc.translatePath( os.path.join( os.getcwd().replace( ";", "" )))
Reply
#12
what are you joining?

PHP Code:
ROOTDIR os.getcwd() 
will suffice.
For python coding questions first see http://mirrors.xbmc.org/docs/python-docs/
Reply
#13
for backwards compability, use os.getcwd().replace(';','')
Reply
#14
Found this info quite usefull:-

http://xbmc.org/jmarshall/2009/02/10/cha...d-plugins/
Reply
#15
Linux is case sensitive. Hence default.py and default.tbn is not the same as Default.py and Default.tbn. This will actually cause the plugin not to load on linux but will work fine on windows. http://forum.xbmc.org/showthread.php?tid=45547
Reply

Logout Mark Read Team Forum Stats Members Help
Tips for coding python scripts / plugins compatible with Linux, Mac, Windows AND Xbox2