Weird scoping issue in options file

Greg Ward <[email protected]>
Newsgroups gmane.comp.version-control.subversion.cvs2svn.devel
Message-ID <[email protected]>
I want to write a custom subclass in a cvs2svn options file, say for
example this:

"""
class MyOutputOption(NewRepositoryOutputOption):
    def __init__(self, *args, **kwargs):
        NewRepositoryOutputOption.__init__(self, *args, **kwargs)
# line 135 in stack trace below
"""

That's perfectly legal, valid, conventional Python that should have no
effect on the behaviour of cvs2svn.  But something about the way
cvs2svn loads options files is messing with my head: when I use
options file, it crashes:

"""
Traceback (most recent call last):
  File "./cvs2svn", line 70, in <module>
    svn_main(os.path.basename(sys.argv[0]), sys.argv[1:])
  File "/home/gward/src/cvs2svn/cvs2svn_lib/main.py", line 101, in svn_main
    run_options = SVNRunOptions(progname, cmd_args, pass_manager)
  File "/home/gward/src/cvs2svn/cvs2svn_lib/run_options.py", line 254,
in __init__
    self.process_options_file(value)
  File "/home/gward/src/cvs2svn/cvs2svn_lib/run_options.py", line
1026, in process_options_file
    execfile(options_filename, g, l)
  File "cvs2svn-test.options", line 150, in <module>
    r'/path/to/svnrepo',
  File "cvs2svn-test.options", line 135, in __init__
    NewRepositoryOutputOption.__init__(self, *args, **kwargs)
NameError: global name 'NewRepositoryOutputOption' is not defined
"""

WTF?  Python is OK with me using 'NewRepositoryOutputOption' at file
scope to define the subclass, but *not* OK with it at function scope?
Colour me confused.  A gross workaround is

class MyOutputOption(NewRepositoryOutputOption):
    def __init__(self, *args, **kwargs):
        from cvs2svn_lib.svn_output_option import NewRepositoryOutputOption
        NewRepositoryOutputOption.__init__(self, *args, **kwargs)

but, really, yuck.

BTW I have the same problem if I use a global identifier at class scope, e.g.

class MyOutputOption(NewRepositoryOutputOption):
    my_re = re.compile(...)

dies with NameError on the reference to 're', even though that module
is imported at the top of the options file.

Anyways: this all smells like there's something funny with the
execfile() call in run_options.py.  And indeed I can make my problems
disappear with this patch:

--- a/cvs2svn_lib/run_options.py
+++ b/cvs2svn_lib/run_options.py
@@ -1018,12 +1018,11 @@

     Store the run options to SELF."""

-    g = {}
-    l = {
+    g = {
       'ctx' : Ctx(),
       'run_options' : self,
       }
-    execfile(options_filename, g, l)
+    execfile(options_filename, g)

   def usage(self):
     self.parser.print_help()

...or, in English, make 'ctx' and 'run_options' global variables in
the options file rather than local variables.

That's all very nice, but does anyone understand what is going on
here?  I thought I knew Python pretty well, but I don't understand why
this fix works. Apparently I don't know everything there is to know
about execfile()!

Greg

------------------------------------------------------
http://cvs2svn.tigris.org/ds/viewMessage.do?dsForumId=1667&dsMessageId=2385356

To unsubscribe from this discussion, e-mail: [[email protected]].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.