For those who patiently read each line

snodx at hotmail.com snodx at hotmail.com
Tue Aug 13 12:01:42 CEST 2002


PYTHON_VERSION=1.5
Oper Sys= Red Hat Linux 7.2
Hardware Platform=Intel Pentium 4 (i686)

Dear everybody,

Dear masters of Python, I need to convert a piece of Python
code to its equivalent Java code. Before I can attempt a conversion
I need to understand what the Python code does exactly.

Kindly read through the following Python scripts and MY intrepretations
of what this scripts do and please tell me where my intrepretation has
gone wrong (the intrepretations have been divided into steps labelled StEp,
the blocks of Python codes are labelled as CoDe BlOcK and finally the lines
of Python codes are labelled as LiNe- I am reaching a dead end at
CoDe BlOcK 3:: I am not able to understand what this code block does)


The first is a file called sendsms which is invoked as:

http://<server-name>/cgi-bin/sendsms?username=""&password=""&to=""&text=""

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--

CoDe BlOcK 1

(4 arguments are passed to this Python script "username", "password", "to"
 and "text"

#!/usr/bin/python

import os, string, sys, urllib                                      #LiNe 1

HOST = "localhost"                                                  #LiNe 2
PORT = 13013                                                        #LiNe 3
USERNAME = "tester"                                                 #LiNe 4
PASSWORD = "foobar"                                                 #LiNe 5

NUMBERS = "~/.sendsms.dat"                                          #LiNe 6

def is_a_phone_number(str):                                         #LiNe 7
    if not str:                                                     #LiNe 8
        return 0                                                    #LiNe 9
    for c in str:                                                   #LiNe 10
        if not c in "0123456789+- ":                                #LiNe 11
            return 0                                                #LiNe 12
    return 1                                                        #LiNe 13

def recipient(arg):                                                 #LiNe 14
    if is_a_phone_number(arg):                                      #LiNe 15
        return arg                                                  #LiNe 16
    f = open(os.path.expanduser(NUMBERS), "r")                      #LiNe 17
    arg = string.lower(arg)                                         #LiNe 18
    number = None                                                   #LiNe 19
    for line in f.readlines():                                      #LiNe 20
        parts = string.split(line)                                  #LiNe 21
        if len(parts) == 2 and string.lower(parts[0]) == arg:       #LiNe 22
            number = parts[1]                                       #LiNe 23
            break                                                   #LiNe 24
    f.close()                                                       #LiNe 25
    if number:                                                      #LiNe 26
        return number                                               #LiNe 27
    print "Unknown recipient", arg                                  #LiNe 28
    sys.exit(1)                                                     #LiNe 29

def sendsms():                                                      #LiNe 30
    to = urllib.quote_plus(recipient(sys.argv[1]))                  #LiNe 31
    text = urllib.quote_plus(string.join(sys.argv[2:], " "))        #LiNe 32
    url="http://%s:%d/cgi-bin/sendsms?username=%s&password=%s&to=%s&text=%s" \  #LiNe 33
        % (HOST, PORT, USERNAME, PASSWORD, to, text)                            #LiNe 34
    f = urllib.urlopen(url)                                                     #LiNe 35
    print f.read()                                                              #LiNe 36
    f.close()                                                                   #LiNe 37

if __name__ == "__main__":                                                      #LiNe 38
    sendsms()                                                                   #LiNe 39

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--


THE EXPLANATORY NOTES ARE HERE AS FOLLOWS:

StEp 1
Import the Python libraries os, string, sys and urllib. I put 2 and
2 together and reasoned out that just as you have header files
stdio,h, stdlib.h e.t.c in a C/C++ code similarly you have os, string,
sys and urllib libraries which are used in Python codes. I searched for
any filename containing urllib in it and voila I got
/usr/lib/python1.5/urllib.py, /usr/lib/python1.5/urllib.pyc and
/usr/lib/python1.5/urllib.pyo. Again I put 2 and 2 together and
reasoned out the the extensions .pyc and .pyo must mean compiled
Python modules (.pyc = Python Compiled). So therefore .py was the actual
source file for the Python library urllib.

Whew! Correspondingly in my RedHat system I managed to locate
/usr/lib/python1.5/os.py and /usr/lib/python1.5/string.py.There
was no sys.py in my RedHat so I assume this is some sort of a
in-built, automatically invokable Python library.

StEp 2
Define and initialize the variables HOST, USER,PORT ,PASSWORD and NUMBER. This
sounds a bit like UNix where ALL variables are treated as strings and where you
dont have datatypes as in C/C++ (char, int or float). So therefore HOST, USER,
PORT e.t.c are string variables.

StEp 3
Define a function is_a_phone_number which checks whether the argument string
is comprised of the digits (0 to 9) and/or a "+", "-" (minus)

StEp 4
Define another function recipient which checks that the entered phone number
is in the list of numbers in the file mentioned in the NUMBERS variable.

StEp 5
A third function sendsms adds a "plus" sign ("+") to the "to" and "text" arguments
A url variable is constructed with the 4 arguments- passed initially- with the
values of the HOST, USER, PORT and PASSWORD variables appended. This url value
is passed on to the urlopen function defined in the urllib library

------------------EnD oF StEpS--------------------

If So FaR InTrEpEtAtIoNs CoRrEcT, tHeN fOlLoW-UpS
(if so far intrepretations correct: then follow-ups)

In StEp 5 we saw that a urlopen() function was being called.
The urlopen function is defined in /usr/lib/python1.5/urllib.py
as follows:

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--


CoDe BlOcK 2

def urlopen(url, data=None):                #LiNe 1
    global _urlopener                       #LiNe 2
    if not _urlopener:                      #LiNe 3
        _urlopener = FancyURLopener()       #LiNe 4
    if data is None:                        #LiNe 5
        return _urlopener.open(url)         #LiNe 6
    else:                                   #LiNe 7
        return _urlopener.open(url, data)   #LiNe 8

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--


EXPLANATORY NOTES::

StEp 1
Invoke the open function in the _urlopener GLOBAL variable.

StEp 2
I scanned through the entire set of Python libraries I had
and found that there was a class called URLopener (defined
in urllib.py) which defined a function called open():

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--


CoDe BlOcK 3

    def open(self, fullurl, data=None):                               #LiNe 1
        fullurl = unwrap(fullurl)                                     #LiNe 2
        if self.tempcache and self.tempcache.has_key(fullurl):        #LiNe 3
            filename, headers = self.tempcache[fullurl]               #LiNe 4
            fp = open(filename, 'rb')                                 #LiNe 5
            return addinfourl(fp, headers, fullurl)                   #LiNe 6
        type, url = splittype(fullurl)                                #LiNe 7
        if not type: type = 'file'                                    #LiNe 8
        if self.proxies.has_key(type):                                #LiNe 9
            proxy = self.proxies[type]                                #LiNe 10
            type, proxy = splittype(proxy)                            #LiNe 11
            host, selector = splithost(proxy)                         #LiNe 12
            url = (host, fullurl) # Signal special case to open_*()   #LiNe 13
        name = 'open_' + type                                         #LiNe 14
        self.type = type                                              #LiNe 15
        if '-' in name:                                               #LiNe 16
            # replace - with _                                        #LiNe 17
            name = string.join(string.split(name, '-'), '_')          #LiNe 18
        if not hasattr(self, name):                                   #LiNe 19
            if data is None:                                          #LiNe 20
                return self.open_unknown(fullurl)                     #LiNe 21
            else:                                                     #LiNe 22
                return self.open_unknown(fullurl, data)               #LiNe 23
        try:                                                          #LiNe 24
            if data is None:                                          #LiNe 25
                return getattr(self, name)(url)                       #LiNe 26
            else:                                                     #LiNe 27
                return getattr(self, name)(url, data)                 #LiNe 28
        except socket.error, msg:                                     #LiNe 29
            raise IOError, ('socket error', msg), sys.exc_info()[2]   #LiNe 30

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--

EXPLANATORY NOTES:

I have reached a dead-end here. I am not able to analyze the Python
code any further. Whatever little I understood I am stating here....

StEp 1
Unwrap the fullurl argument. This probably means (according to the
definition of the unwrap function in string.py) that if fullurl were
of the form <URL:type//host> then convert it to type://host

StEp 2
I am not able to understand the elements in the if block- tempcache and
tempcache.has_key. I scanned through the entire set of .py Python
libraries on my RedHat but found no mention of tempcache, EXCEPTING
ofcourse in /usr/lib/python1.5/urllib.py.

There is a mention of tempcache in one of the functions of URLopener called:
def __init__(self,proxies=none):

self.tempcache=none

Observing the way string variables have been constructed so far I
assume that self.tempcache must be a string variable which has been
assigned a Null value. 

Now for tempcache.has_key(). There was no definition of has_key in urllib
itself. So it had to be in one of the libraries urllib was importing.

import string
import socket
import os
import sys

No definitions of has_key in string.py and os.py. I then set out
to search socket.py. I got only one but the filename was in uppercase:

/usr/lib/python1.5/plat-linux-i386/SOCKET.py

Assuming that this was the socket library referred in the urllib
I searched for has_key in this file but no success.

Having eliminated all possibilites I concluded that has_key must
be defined in the sys library. But as I had said earlier there
was no sys.py.

So has_key is abandoned now (and hence the whole if block is
abandoned) and we move on to the next step.

StEp 3

type, url=splittype(fullurl)

This statement as far as my understanding goes means declare and initialize
2 variables type and url as the value obtained from splittype(fullurl)
Judging by the way splittype() has been defined (in urllib.py):

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--

CoDe BlOcK 4

def splittype(url):                            #LiNe 1
    global _typeprog                           #LiNe 2
    if _typeprog is None:                      #LiNe 3
        import re                              #LiNe 4
        _typeprog = re.compile('^([^/:]+):')   #LiNe 5

    match = _typeprog.match(url)               #LiNe 6
    if match:                                  #LiNe 7
        scheme = match.group(1)                #LiNe 8
        return scheme, url[len(scheme) + 1:]   #LiNe 9
    return None, url                           #LiNe 10

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--

I conclude that splittype() returns the scheme of a url such as the
different parts of the url <protocol>, <domain type=www,www1,www2 e.t.c>,
<domain name>, <domain extension=com,org,net...>

StEp 4

I am skipping lines 9 to 13. This has something to do with proxies
with which I am not interested right now.

name="open_"+type

Construct a variable name prepending it with the value "open_" and
then the value of the type variable.

StEp 5

I did not get any definition of the function hasattr() so I assume
that this is defined in the mysterious sys library.

Within the if no hasattr() block the statement open_unknown(fullurl)
throws an IOError exception as per the definition of open_unknown()
in urllib.py

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--

CoDe BlOcK 5

def open_unknown(self, fullurl, data=None):                    #LiNe 1
        type, url = splittype(fullurl)                         #LiNe 2
        raise IOError, ('url error', 'unknown url type', type) #LiNe 3

__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--
--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__
__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--


SUMMARY

THAT's it. The dead end has arrived.

We started with intrepreting the sendsms Python script found that
it was calling the urlopen() function in the urllib Python module
which in turn was calling the open() function defined in the
URLopener class in urllib module. I am unable to analyze what the
open() function does as it seems to raise only errors.

Any help would be greatly appreciated.

The originator of this sendsms Python script cannot be contacted
right now. This sendsms Python script comes as part of the open
source Kannel 1.2.0 SMS gateway package.I need to convert it to
an equivalent Java code.

Thankx for putting up with me.

SNODX

Please Note: If you need any more input please let me
             know. Also my e-mail account snodx at hotmail.com
             is not working. Please keep the replies to this
             post.





More information about the Python-list mailing list