2

For previous versions of the question see the revision history - managed to come up with a minimal executable example that reproduces the problem

# module test.py
import shlex
from test2 import Parser

class Test(object):
    sync_client = None

    def __init__(self):
        self.__class__.sync_client = 1
        parser = Parser(description='desc') # was before the assignment - egal
        while True:
            cmd = shlex.split(raw_input('> ').strip())
            parser.parse_args(cmd)

    @classmethod
    def newRequestClient(cls):
        print cls.sync_client # None

if __name__ == "__main__":
    Test()

# module test2.py
import argparse

class Share(object):
    class _ShareAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            from test import Test
            print Test.sync_client # None
            Test.newRequestClient()

    def __call__(self, subparsers):
        parser_a = subparsers.add_parser('name')
        parser_a.add_argument(dest='dest', help='help2',
                              action=Share._ShareAction)

class Parser(argparse.ArgumentParser):
    def __init__(self, description, add_h=True):
        super(Parser, self).__init__(description=description, add_help=add_h)
        subparsers = self.add_subparsers(title='Commands')
        subparsers._parser_class = argparse.ArgumentParser
        Share()(subparsers)

Run test.py and type name 123 in the prompt to see the Nones printed. Well maybe it is something obvious - it's been hours :)

EDIT: For the reproducer posted here this:

if __name__ == "__main__":
    from test import Test
    Test()

works. Adding from sync import Sync (and variations) in my main did not help however. I finally "solved" it by:

class Share(Command):
    class _ShareAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            sync = sys.modules['__main__']
            print sync.Sync.sync_client # <SyncClient(SyncClient, started 6084)>
            sync.Sync.newRequestClient(host=namespace.host, repo=values)

But I do not yet fully understand why from sync import Sync did not work.

FINALLY: thanks to a comment by @MartijnPieters:

# module watcher.sync

if __name__ == "__main__":
    from watcher.sync import Sync
    Sync().main()

This looks ugly though so feel free to comment (or even add an answer) on how I could avoid it.

9
  • 1
    Your new example involves a lot of other complications. How are you using those classes? Commented Sep 21, 2014 at 21:09
  • I don't see an instance of Sync ever being created in your new code. Commented Sep 21, 2014 at 21:14
  • @BrenBarn: will edit with more details but what especially you want to know ? Commented Sep 21, 2014 at 21:19
  • 2
    the minimal executable example that reproduces your problem Commented Sep 21, 2014 at 21:21
  • @joaquin: Working on this - it is not trivial though Commented Sep 21, 2014 at 21:22

1 Answer 1

3

You misspelled __init__:

def __int__(self):

You are missing an i and the method is simply not called. Correct the error and your test works.

Demo:

>>> class Test(object):
...     class_attr = None
...     def __init__(self):  # note the spelling
...         self.__class__.class_attr = 1
...     @staticmethod
...     def static_meth():
...         print Test.class_attr
...     @classmethod
...     def class_meth(cls):
...         print cls.class_attr
... 
>>> t = Test()
>>> Test.class_attr
1
>>> Test.static_meth()
1
>>> Test.class_meth()
1
>>> t.class_meth()
1
>>> t.static_meth()
1

In you updated code you have two issues:

First you create an instance of Parser before the class attribute has been set. The self.__class__.sync_client = 1 line simply hasn't executed yet when Parser.__init__ is being called.

You then confuse the main script and the test module. Python imports the main script as __main__, not test. If you move the Test class out to a separate module or use from __main__ import Test your code will work.

See Importing modules: __main__ vs import as module

Sign up to request clarification or add additional context in comments.

16 Comments

Well this is true - in my real class hadn't mispelled __init__ though - let me see a minute
@Mr_and_Mrs_D: you misspelled something; see my demo (from a 2.7.8 session).
I edited the question with my original code - will keep looking but I hope you see something I don't :)
Well - may be an import issue ? I do from watcher.sync import Sync and this is run before Sync.__init__() runs - at that time the debugger shows me a Sync class that has sync_client == None - could it be this ?
@Mr_and_Mrs_D: no, that is not frowned upon. What won't work is putting the script file inside a package, and then expect to be part of the package namespace.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.