4

Update/Solution: the answer is below, from Zack. The problem was, indeed, DOS line endings on the script file itself, clenotes.cmd. Since I futzed with the various files so much, I deleted the whole directory and then re-downloaded a fresh copy from HERE. I ran Zack's perl script on the file just like so:

perl -pi.bak -e 's/[ \t\r]+$//' clenotes.cmd

I then edited the command execution just slightly so that the final script became:

CWD=`dirname $0`
JYTHON_HOME="$CWD"
LIB_DIR="$JYTHON_HOME/lib"
NOTES_HOME="/opt/ibm/lotus/notes/"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NOTES_HOME
java -cp "$LIB_DIR" -jar "$LIB_DIR/jython.jar" -Djython.home="$CWD/" -Dpython.path="$LIB_DIR:$CWD/ext" -Djava.library.path="$NOTES_HOME" "$LIB_DIR/clenotes/cletes/clenotes.py" "$@"

That was it -- everything else worked. No edits needed to clenotes.py or clenotes.cfg. Many thanks for sticking with the question, which I guess ended up being quite simple.


Update: I'm cutting down on some of the code to make this more readable and remove unnecessary information from the post.


I'm trying to get Lotus Notes command line to work on Linux and am having an issue with something related to sys.argv[1:] in the python file. The windows script is here:

@echo off
@setlocal 
set CWD=%~dp0
set JYTHON_HOME=%CWD%
set LIB_DIR=%JYTHON_HOME%/lib
java -cp %LIB_DIR% -jar %LIB_DIR%/jython.jar -Djython.home=%CWD%  -python.path=%LIB_DIR%;%CWD%/ext %LIB_DIR%/clenotes/clenotes.py  %*

@endlocal

I was having a tough time with variables, so for Linux, it simply looks like this:

java -cp ./lib/ -jar ./lib/jython.jar -Djython.home=./ -Dpython.path=./lib:./ext -Djava.library.path=/opt/ibm/lotus/notes/ ./lib/clenotes/clenotes.py $*

I run it from within the directory. In any case, what puzzles me is that it's not picking up any options I pass from the command line. clenotes.cmd --help results in

No commands specified. Use --help option for usage.

Here is the section where the command line arguments are supposed to be parsed:

def main():    

  Output.log("Entering %s v%s" % (PROGRAM_NAME,VERSION),Output.LOGTYPE_DEBUG)
  cliOptions2=[]
  for opt in cliOptions:
    opt2=opt.replace('--','')
    opt2=opt2.replace('!','=')
    cliOptions2.append(opt2)
  opts=[]
  args=[]
  try:
    opts, args = getopt.getopt(sys.argv[1:], '', cliOptions2)

I'm using Python 3.1.3 on Arch Linux 64bit in a 32bit chroot environment. Can I provide anything else?

Just in case it's needed... HERE is the whole clenotes.py file.

Also, as requested in the comments, the config file (which contains the help message and viable options/arguments, is HERE


Update

After a lot of fiddling, the best progress I have made has been to examine what it's setting as opts and args in the (main) method. Most surprising was that when passing an argument and then looking at it's parsed result using print sys.argv, the option would come up with a trailing \r in it. For example:

clenotes.cmd appointments
args is ['appointments\r']

On Windows I did the same and args was reported as ['appointments']. Furthermore, manually setting args=['appointments'] and then commenting out the section where getopt.getopt is assigning a value worked.

Lastly, I've found that when using multiple arguments, n-1 of them get interpreted and used while the nth one gets ignored. This is kind of a workaround since I can actually use the script... but obviously it's not preferred. If I want to look at today's appointments, I can execute clenotes.cmd appointments --today --today and it will work. sys.argv will spit out: ['appointments', '--today', '--today\r'].

So... what's causing the trailing \r? I'm thinking it has to do with the actual script. Note it again:

java -cp ./lib/ -jar ./lib/jython.jar -Djython.home=./ -Dpython.path=./lib:./ext -Djava.library.path=/opt/ibm/lotus/notes/ ./lib/clenotes/clenotes.py $*

So... bunch of path stuff and then the actual python file: clenotes.py $*

I got the $* from HERE

Is it picking up the carriage return??

Community
  • 1
  • 1
Hendy
  • 10,182
  • 15
  • 65
  • 71
  • It looks like this is using Jython, so Python 3.1.3 has nothing to do with it. The latest version of Jython is 2.5.2 RC3. – Thomas K Feb 04 '11 at 00:03
  • From what I can tell, this is using python's `ConfigParser` to read a config file, and to generate from that config file `cliOptions`, which in turn is being used to define the `long_options` for `getopt`. But that can't be right... that would be insane. Still -- clenotes.cfg does exist, right? Because if it doesn't, and if I'm reading this code right, then that's the problem. – senderle Feb 04 '11 at 00:11
  • Yeah... looking over this more, that's what it's doing. Weird. Could you post the "options" section of clenotes.cfg? – senderle Feb 04 '11 at 00:41
  • @senderle: thanks for taking a look. I added the clenotes.cfg file. The [options] section is toward the top. Might I need to alter the path the clenotes.py file is using to find clenotes.cfg? Perhaps it's just not finding it? Oh... and could you let me know why you think it's insane? :) – Hendy Feb 04 '11 at 15:31
  • @senderle: just tested that theory. If I add a `print cliOptions` after where `ConfigParser.ConfigParser()` and `config.readfp` opens clenotes.cfg... it prints the options list out like so: `['--help', '--server-name!', '--exec-time'.....` So it does seem to be finding the file, evidenced by setting the cliOptions variable. – Hendy Feb 04 '11 at 15:36
  • @Hendy, regarding insanity, from a UI perspective, I would expect a program without a config file to still be able to parse command line args. Basically, clenotes.py is useless without a config file. The "do not change existing" at the top of the config sections says it all. – senderle Feb 04 '11 at 19:52
  • 1
    Ok, the next step is to see whether getopt is behaving as expected. Could you tell me what you see when you add a `print opts, args` after this line: `opts, args = getopt.getopt(sys.argv[1:], '', cliOptions2)` and run clenotes.py with some valid options and commands? – senderle Feb 04 '11 at 19:57
  • Yeah -- I've been fiddling with stuff like that. I know a bit of java and can kind of follow what's going on. The issue really is in the sys.argv[1:] line or in the line running the script. See my update for why I say so. – Hendy Feb 04 '11 at 20:02
  • 1
    Also, if you can figure out where the log file is, you should enable logging by changing the last line of the config file to `write_log: true` (or possibly `True` -- or a filename? -- I don't know how Output works.) – senderle Feb 04 '11 at 20:02
  • Well I don't think it's `sys.argv[1:]` because that's perfectly standard -- as you say, that's what the docs use. – senderle Feb 04 '11 at 20:06
  • Log output from `clenotes.cmd mail` is this (I stripped out stupid stuff): `Opts: [], Args: ['mail\r'], [], ['mail\r']` – Hendy Feb 04 '11 at 20:21
  • Looking over the source more, I find the `except getopt.GetoptError,e:` clause bewildering -- it's not exiting as it says it should. This seems like it might be papering over a GetoptError. Could you try removing that clause and see what happens? – senderle Feb 04 '11 at 20:28
  • Removed that whole section from (main) -- same result. If you find it helpful/of note, I have this running on a Windows machine and just enabled logging and it gives ['today'] instead of the ['today\r'] on Linux. Could the issue be with the `$*` in the actual script? Is the script itself not be picking up command line options properly? – Hendy Feb 04 '11 at 20:33
  • Also, if I remove the whole `getopt.getopt` section and set args to `['today']` manually where it currently has `args=[]`... it works properly. – Hendy Feb 04 '11 at 20:38
  • Oddly, inserting a `print sys.argv[0]` as well as for 1 and 2... `[0]` outputs the name of the script (as expected), `[1]` outputs the first command (even the illusive `--help`, so we know at least it's in the recognized commands), but `[2]` gives an `index out of range error`. It's like it doesn't see the second option. One option still gives the trailing `" not recognized.` I think something in how it's parsing the command line options is messing things up. Perhaps it's attached to the use of `$*` in the script or whatever is causing it to pick up the trailing `\r` in the args variables? – Hendy Feb 04 '11 at 21:06
  • Some success! Oddly, `clenotes.cmd today mail` results in it executing the `today` command (mail is ignored). Doing `clenotes.cmd --help mail` results in it executing `--help`... to get something with a command and option like `clenotes.cmd appointments --today`... I actually have to insert a "dummy" command at the end. So the issue is that `clenotes.cmd opt[1] cmd[2] opt[3]` will only recognize n-1 actual items. I think it's the `\r` at the end of the last command. Where would that be coming from? – Hendy Feb 04 '11 at 21:14
  • Are you using bash to run the command? – senderle Feb 04 '11 at 22:18
  • 1
    I don't think this will help with the *current* problem, but except in *very rare* circumstances which do not apply here, you should use `"$@"` (exactly as shown, including double quotes) instead of `$*` when you want to pass a shell script's entire argument list down to a nested command. – zwol Feb 04 '11 at 22:24
  • To clarify, I can't imagine a situation in which bash would add `\r`, so if the script is adding `\r` it must not be a bash script – senderle Feb 04 '11 at 22:25
  • Yeah, Zack is right, I wasn't paying very much attention to that. – senderle Feb 04 '11 at 22:29
  • @Zack: I did change that now. By "double" quotes... are you meaning an apostrophe (`'`) twice on each side or a quotation mark (`"`) once on each side? The code block font makes it hard to tell... – Hendy Feb 04 '11 at 22:39
  • @senderle: no bash. It's just the command as you see it in a file called clenotes.cmd. Originally there were some variable settings going on, but I just manually input my path because I wanted to eliminate sources of issues and narrow it down to the real problem. – Hendy Feb 04 '11 at 22:41
  • I'm not convinced the `\r` s are coming from the command line at all. I said in my answer where I think they're coming from, but just to be sure, could you try adding a line reading just "`print >> sys.stderr, repr(sys.argv)`" to `clenotes.py` *immediately* after the existing `import sys` line? – zwol Feb 04 '11 at 22:41
  • I mean a quotation mark, once on each side. Not an apostrophe. – zwol Feb 04 '11 at 22:42
  • 1
    "It's just the command as you see it in a file called clenotes.cmd." Hmm. What does `cat -v clenotes.cmd` print? – zwol Feb 04 '11 at 22:44
  • @Zack: changed to quotation. The print line results in the same thing I get below with my `print sys.argv` line. It is `['./clenotes.py', 'appointments', '--today\r']`. Basically it's always just `['path/to/script.py','opt/arg1','opt/arg2',...,'opt/argn\r']`... every time. – Hendy Feb 04 '11 at 22:47
  • @Zack: `cat -v clenotes.cmd` yields `java -cp ./lib/ -jar ./lib/jython.jar -Djython.home=./ -Dpython.path=./lib:./ext -Djava.library.path=/opt/ibm/lotus/notes/ ./lib/clenotes/clenotes.py "$@"^M` – Hendy Feb 04 '11 at 22:50
  • 1
    Ow ow ow. Okay, I know what's wrong. The `\r` is coming from `clenotes.cmd`. It is bash (or whatever shell you have) that is misinterpreting the DOS line ending in that file as part of the last argument to the command. Try executing that perl command I suggested below, on `clenotes.cmd`. – zwol Feb 04 '11 at 23:40

2 Answers2

5

I think your problem is that clenotes.cfg has DOS line endings, which Python is misinterpreting. Try changing this line of clenotes.py

config.readfp(open('%sconfig/clenotes.cfg' % System.getProperty('jython.home')))

to read

config.readfp(open('%sconfig/clenotes.cfg' % System.getProperty('jython.home'), "rU"))

The "rU" tells Python that even though it's running on a Unix system it should be prepared to cope with a file containing DOS line endings. See http://docs.python.org/library/functions.html#open -- scroll down to the paragraph that begins "In addition to the standard fopen() modes...".

(Or you could run this command: perl -pi.bak -e 's/[ \t\r]+$// clenotes.cfg -- that will convert it to Unix line endings. In your shoes I would probably do both.)

(If neither of the above suggestions helps, the next thing I would try is hitting clenotes.py itself with the above perl command. I don't see how that could be the problem, but if the \r characters are not coming from clenotes.cfg, the .py file is the only plausible remaining source.)

(EDIT: Based on your comments on the question itself, I now think it's clenotes.cmd, the shell script wrapper, that needs to be converted from DOS to Unix line endings.)

zwol
  • 135,547
  • 38
  • 252
  • 361
  • +1 for the obvious. And for always using an IDE that uses the appropriate line endings. – Falmarri Feb 04 '11 at 22:40
  • Yeah I had to leave and just as I was walking out the door, I realized that clenotes.cmd must be dos formatted. But that still doesn't explain why the options aren't being parsed. – senderle Feb 05 '11 at 00:38
  • I'm still gonna blame that on the DOS line endings in the .cfg file till we hear different. – zwol Feb 05 '11 at 00:44
  • @Zack: I copied/pasted your line just to make sure I wasn't getting it wrong, but it produces `IOError: Unknown open mode:rU` from line 29 (the line we modified). The perl diddy *did* alter the result of the sys.argv array, but it was needed on the actual script `clenotes.cmd` which had trailing `^M`s at the end of the lines. `clenotes.cmd today` now produces `['today']` in sys.argv instead of `['today\r']`. Unfortunately, --help is still not parsed. It's reading arguments but not options. – Hendy Feb 05 '11 at 06:52
  • Whoops -- spoke too soon! Just tried --help again and it worked! So did --noheader. Unfortunately, I'm not in my company's network and even when using a vpn connection it's not finding my database. I'll run through some commands on Monday and retry -- if all is well, I consider that this was the issue. I'll post links to this on both locations where this command line is publicized. Thanks everyone!! – Hendy Feb 05 '11 at 06:57
  • I guess "U" is a feature of CPython that hasn't been picked up by your version of Jython. I'd report that to the Jython people as (at the least) a documentation bug, I did check their version of the docs and it appears to be supported -- but they seem to have copied most of their documentation verbatim from CPython, so I could see this being an oversight. – zwol Feb 05 '11 at 16:06
  • Yup -- this is the fix. See the update in the original post. Thanks!! – Hendy Feb 08 '11 at 17:51
3

I'll have to keep looking to figure out where that \r is coming from. But in the meanwhile, this problem has become much simpler. Once the args are parsed, do this:

args = [arg.strip() for arg in args]

That will get rid of the \r

EDIT: But wait -- is this only a partial solution? Is it still not parsing options correctly?

EDIT2: Seems like the \r needs to be stripped earlier. When there's no command, the /r never gets stripped, because the above only strips \r after getopt is done. This should have been obvious to me before -- instead of passing sys.argv[1:] here

opts, args = getopt.getopt(sys.argv[1:], '', cliOptions2)

modify it first

argv = [arg.strip() for arg in sys.argv[1:]]
opts, args = getopt.getopt(argv, '', cliOptions2)

You could also just do sys.argv[-1] = sys.argv[-1].strip()... but the c programmer in me starts to feel a bit queasy looking at that. Probably irrational, I know.

Or just do what Zack said and convert clenotes.cmd to linux format -- however, note that stripping here will ensure that other people will not have to solve the same problem over again. (On the other hand, it's a little ugly, or at least mysterious to people not expecting such problems.)

senderle
  • 145,869
  • 36
  • 209
  • 233
  • This is just goofy. I added your line below the `opts,args=getopts.getopts...` line. I also (for the heck of it) added `print sys.argv` as well. The result is quite interesting. 1) `clenotes.cmd today` now works. 2) `clenotes.cmd --help` still does not work unless it's followed by another option. 3) Most puzzling is that the output of `print sys.argv` is the *same* regardless of whether I have your `arg.strip` line there or not. It is always: `['./clenotes.py', 'today\r']`. The `\r` is still there at that point! You're right: it's still not picking up --options unless a command follows. – Hendy Feb 04 '11 at 22:36
  • @Hendy, see above for my new thought about this. – senderle Feb 05 '11 at 01:13