Oracle Blog

For the Adrenaline Junkie

Monday Oct 20, 2008

I'm in the midst of debugging a snoop implementation and I wanted to recompile with gcc and use gdb.
I saved the output from the make command and basically used vi to put each .o file on a single line:

A conversion specifier contains two or more characters and has the following components, which must occur in this order:
1. The "%" character, which marks the start of the specifier.
2. Mapping key (optional), consisting of a parenthesised sequence of characters (for example, (somename)).

So, this code would be good for printing, but not necessarily for doing more complex manipulations.

Tuesday Oct 07, 2008

I played about in the interactive Python shell trying to understand
the data and how to tie it together. I learned about the difference
between exec and eval for Python. I learned about capturing
stdio and stdout for exec, but I couldn't figure out a way to
automatically create variables in the proper scope in Python.

> This is something I've been trying to figure out for some time. Is
> there a way in Python to take a string [say something from a
> raw_input] and make that string a variable name? I want to to this so
> that I can create class instances on-the-fly, using a user-entered
> string as the instance name.
This comes up regularly from beginners and is nearly always a bad
idea!
The easy solution is to use a dictionary to store the instances.

Nice to know I'm not the first to want to do this. But it did
get me thinking, I have been calling this set of Perl scripts
'data dictionaries' for longer than I care to remember. And the
code is not very legible at times. So, I decided to redo the script
as:

I was suspicious about that extra newline I mentioned way back in The simple version of the old perl script. I suspected that the entry line
still had an extra one that I needed to remove. I.e., the data dictionary has a key for 'dictionary\\n' and
not 'dictionary'.

So I learned what I set out to do. I may never use this script, but it helped me learn some
things the hard way. I didn't show all of the little syntax errors I had to fix (forgetting the ':',
not indenting in the interactive shell, etc). But hopefully, I'll remember them.

I'll also claim that the script does meet my needs as did the old one. If I add a new field
to the flat file, I won't have to change the script to get the current output! And yes, I just
tried that and I didn't have a problem.

I could do some more error checking (i.e., don't access an entry unless it is set), but I've
already gone above the error checking in the Perl script.

And my intent was to strip out all of the leading spaces. I didn't have to,
but I created a simple test case with the first line pushed over by a tab and
the second line pushed over by 8 spaces. The first one worked correctly and the second did not:

Update, I wasn't thinking correctly here, I knew I had two bad lines here and I didn't know why. After solving the coding problem, I can see
that both lines of input failed. The header line is being treated here as if it were a normal line and being processed.

Well d'oh, even in Perl I just told it to strip out one character. I've got to
tell it that while there is whitespace, strip it out:

for line in open(sys.argv[1]):
while line.isspace(): line.lstrip()

And this doesn't work either. At which point I realize it must be because strings are immutable, right? I mean it is never changing! Note I get to the right conclusion, but for the wrong reasons. If it were immutable and the string had whitespace at the start, I should be stuck in an endless loop here. See the ending section for that analysis.

It also points out that I never did anything with that line.lstrip().
It never changes line, but does create a reference to a new string. Which we can see here:

>>> st2 = " This is the radio clash!"
>>> print st2.lstrip()
This is the radio clash!
>>> print st2
This is the radio clash!
>>>

Another mistake I just made

Which should be an endless loop according to what I know now. But nothing
gets done. Which means that st2.isspace() is FALSE. And a help(st2.isspace) shows that:

Help on built-in function isspace:
isspace(...)
S.isspace() -> bool
Return True if all characters in S are whitespace
and there is at least one character in S, False otherwise.

I.e., my misunderstanding of st2.lstrip() being immutable made me think that st2.isspace() worked on the first character of the string. Actually, I made a bad assumption based on what I thought C would do. My bad.

So I don't ever want to do that while loop on a string which is really all whitespace.

All the reading in the world about Python strings will not help me understand the immutability of them as much as this simple example.

My first pass at a Python version of An old perl script reveals my inner C programmer. I've restricted the program to the simple version which does not generate the column name as local variables - first I want to get my proof of concept correct:

Monday Oct 06, 2008

I'm pretty used to referencing variables inside print blocks in Perl. I'm not at all comfortable
with Python. I have a block of code that I want to change the 'onhg' to come out of a config file.
So I set up a scratch directory and make a bare bones implementation:

[th199096@jhereg ~/scratch]> ./updateoso.py
updateoso.py [-n] <-R repo root>
-n: dry run, no email sent (displayed on stdout)
-R: root dir of repo (where .hg is)
Attempt to send changes to
ssh://hg.opensolaris.org/hg/onnv/onnv-gate
This script must be run as user "onhg".
You should set up RBAC and use pfexec(1).

Okay, I should have known that wasn't going to work. It would
probably work in the code (we'll see later), but for now this
will work:

>>> updateoso.config.GATE_USER = "duke"
>>> reload(updateoso)
updateoso.py [-n] <-R repo root>
-n: dry run, no email sent (displayed on stdout)
-R: root dir of repo (where .hg is)
Attempt to send changes to
ssh://hg.opensolaris.org/hg/onnv/onnv-gate
This script must be run as user "duke".
You should set up RBAC and use pfexec(1).
<module 'updateoso' from 'updateoso.pyc'>

To be honest, I knew the reference would work, but I expected it to be reset.
In retrospect, I can see that I reloaded updateoso and etc/config. Just something
to get used to. I could force it to 'reset' via:

>>> reload(etc/config)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'etc' is not defined
>>> from etc reload(config)
File "<stdin>", line 1
from etc reload(config)
\^
SyntaxError: invalid syntax
>>> reload(updateoso.config)
<module 'etc.config' from 'etc/config.pyc'>
>>> reload(updateoso)
updateoso.py [-n]
-n: dry run, no email sent (displayed on stdout)
-R: root dir of repo (where .hg is)
Attempt to send changes to
ssh://hg.opensolaris.org/hg/onnv/onnv-gate
This script must be run as user "onhg".
You should set up RBAC and use pfexec(1).
<module 'updateoso' from 'updateoso.pyc'>

I know I can find most of what I want on the net, but I wanted a printed resource.

Anyway, I had a question right off the bat - about whether if file a imports modules b and c, what happens if c also imports b? Deeper in the book that I've read, it does state that an import is equivalent to load the file if it is not already loaded. But that doesn't help me learn the language. :->

The following example is quite simple, but effective in answering the question for me:

Test 3

> ./a.py
This is the file a.py!
importing b from a
This is the file b.py!
Called from /home/tdh/python/b.py
importing c from a
This is the file c.py!
> ./a2.py
This is the file a.py!
importing c from a
This is the file b.py!
Called from /home/tdh/python/b.pyc
This is the file c.py!
importing b from a
and b's title is
This is the file b.py!

I can see the "nesting" if I pop into an interactive session:

> python
>>> import a2
This is the file a.py!
importing c from a
This is the file b.py!
Called from b.pyc
This is the file c.py!
importing b from a
and b's title is
This is the file b.py!
>>> a2.__dict__.keys()
['c', 'b', 'title', '__builtins__', '__file__', '__name__', '__doc__']
>>> a2.c.__dict__.keys()
['b', 'title', '__builtins__', '__file__', '__name__', '__doc__']
>>> a2.c.b.__dict__.keys()
['__builtins__', '__name__', '__file__', '__doc__', 'title']

But this doesn't answer my question of how to figure this out
recursively. I.e., I guess I am looking for a parent "pointer" and
I could walk it to get my answer.