AttributeError: 'module' object has no attribute 'run_controller' #18

Open
opened 2018-10-29 17:25:19 +00:00 by rtyler · 7 comments
Owner

Author: @yang Posted at: 22.09.2010 20:02

$ spawning --version
0.9.4

$ paster --version
PasteScript 1.7.3 from /home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg (python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41))

$ grep Spawning out/0.ini 
use = egg:Spawning

$ paster serve out/0.ini
Starting server in PID 7881.
Traceback (most recent call last):
  File "/home/yang/work/pod/env/bin/paster", line 9, in <module>
    load_entry_point('PasteScript==1.7.3', 'console_scripts', 'paster')()
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 84, in run
    invoke(command, command_name, options, args[1:])
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 123, in invoke
    exit_code = runner.run(args)
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 218, in run
    result = self.command()
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py", line 303, in command
    serve()
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py", line 287, in serve
    server(app)
  File "/home/yang/work/pod/env/lib/python2.6/site-packages/spawning/paste_factory.py", line 99, in run
    spawning_controller.run_controller(
AttributeError: 'module' object has no attribute 'run_controller'
Author: @yang Posted at: 22.09.2010 20:02 ``` $ spawning --version 0.9.4 $ paster --version PasteScript 1.7.3 from /home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg (python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)) $ grep Spawning out/0.ini use = egg:Spawning $ paster serve out/0.ini Starting server in PID 7881. Traceback (most recent call last): File "/home/yang/work/pod/env/bin/paster", line 9, in <module> load_entry_point('PasteScript==1.7.3', 'console_scripts', 'paster')() File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 84, in run invoke(command, command_name, options, args[1:]) File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 123, in invoke exit_code = runner.run(args) File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py", line 218, in run result = self.command() File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py", line 303, in command serve() File "/home/yang/work/pod/env/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py", line 287, in serve server(app) File "/home/yang/work/pod/env/lib/python2.6/site-packages/spawning/paste_factory.py", line 99, in run spawning_controller.run_controller( AttributeError: 'module' object has no attribute 'run_controller' ```
Author
Owner

Author: @rtyler Posted at: 25.09.2010 18:07

To be honest I don't use, nor have I ever used paster with Spawning or anything else. Is there any chance you could jump into the paste_factory module and come up with a patch? :-/

Author: @rtyler Posted at: 25.09.2010 18:07 To be honest I don't use, nor have I ever used paster with Spawning or anything else. Is there any chance you could jump into the paste_factory module and come up with a patch? :-/
Author
Owner

Author: @yang Posted at: 26.09.2010 06:53

Ah. I'm misunderstanding this part:

"Spawning can be used to launch a wsgi application from the command line using the "spawn" script, or using Python Paste. To use with paste, specify use = egg:Spawning in the [server:main] section of a paste ini file."

What then does it mean to "use with paste"? (If I just invoke spawning directly, I don't need to adjust the paste ini.)

This isn't a big deal as I'm just invoking spawning directly now, but consider updating/clarifying the docs?

Author: @yang Posted at: 26.09.2010 06:53 Ah. I'm misunderstanding this part: "Spawning can be used to launch a wsgi application from the command line using the "spawn" script, or using Python Paste. To use with paste, specify use = egg:Spawning in the [server:main] section of a paste ini file." What then does it mean to "use with paste"? (If I just invoke spawning directly, I don't need to adjust the paste ini.) This isn't a big deal as I'm just invoking spawning directly now, but consider updating/clarifying the docs?
Author
Owner

Author: @rdw Posted at: 01.10.2010 21:59

I think it just means that spawning understands Paste Deploy's .ini files. Here's how you launch Spawning with them:

spawning --factory=spawning.paste_factory.config_factory development.ini

Author: @rdw Posted at: 01.10.2010 21:59 I think it just means that spawning understands Paste Deploy's .ini files. Here's how you launch Spawning with them: spawning --factory=spawning.paste_factory.config_factory development.ini
Author
Owner

Author: @yang Posted at: 01.10.2010 22:01

Yes, that's what I do and that's what I meant with "just invoke spawning directly." Another way to spin this question: what is "use = egg:Spawning" for?

Author: @yang Posted at: 01.10.2010 22:01 Yes, that's what I do and that's what I meant with "just invoke spawning directly." Another way to spin this question: what is "use = egg:Spawning" for?
Author
Owner

Author: @rdw Posted at: 01.10.2010 22:12

Man I have no idea. I bet that's something that was working at one point but got broken. I'd suggest removing it from the README until we figure out how Paste works. I've looked at its documentation a bunch of times and I still have no idea what the deuce paste factories are for.

Author: @rdw Posted at: 01.10.2010 22:12 Man I have no idea. I bet that's something that was working at one point but got broken. I'd suggest removing it from the README until we figure out how Paste works. I've looked at its documentation a bunch of times and I still have no idea what the deuce paste factories are for.
Author
Owner

Author: @countergram Posted at: 11.11.2010 21:54

Since I use Pylons I tried to fix this so use = egg:Spawning would work. It appears to be impossible without changing much more of spawning, and should be removed from the doc in favor of saying that spawning is meant to be used only as a command-line script.

Because os.execve() is called to replace child processes with new processes just after os.fork(), the child processes can receive only strings from the parent. In the example above of launching from the command line, each child parses the .ini file separately on startup. In other prefork and/or threaded wsgi servers I've used (e.g. flup), the parent parses the config file once, and the wsgi application is available as an object to children (because only fork() is used).

The reason I think use = egg:Spawning can't work is that Paste Deploy is based on the idea of your config file referencing an entry point/function that creates and returns a wsgi application. This wsgi application is not in module global scope (it was created inside a function) and therefore cannot be pickled or referred to by a string name.

Author: @countergram Posted at: 11.11.2010 21:54 Since I use Pylons I tried to fix this so `use = egg:Spawning` would work. It appears to be impossible without changing much more of spawning, and should be removed from the doc in favor of saying that spawning is meant to be used only as a command-line script. Because os.execve() is called to replace child processes with new processes just after os.fork(), the child processes can receive only strings from the parent. In the example above of launching from the command line, each child parses the .ini file separately on startup. In other prefork and/or threaded wsgi servers I've used (e.g. flup), the parent parses the config file once, and the wsgi application is available as an object to children (because only fork() is used). The reason I think `use = egg:Spawning` _can't_ work is that Paste Deploy is based on the idea of your config file referencing an entry point/function that creates and returns a wsgi application. This wsgi application is not in module global scope (it was created inside a function) and therefore cannot be pickled or referred to by a string name.
Author
Owner

Author: @sayap Posted at: 12.08.2012 00:31

With the following diff, I can get paster serve to work fine with Spawning. The first 2 hunks add support for --app-name and --server-name, while the last 2 hunks unbreak support for use = egg:Spawning. I got lazy with arguments parsing, so I just pull in PasteScript as another dependency on top of PasteDeploy.

Note that I have only done minimal testing with this...

diff --git a/spawning/paste_factory.py b/spawning/paste_factory.py
index 0442652..cf89efb 100644
--- a/spawning/paste_factory.py
+++ b/spawning/paste_factory.py
@@ -24,27 +24,33 @@ import os
 import sys

 from paste.deploy import loadwsgi
+from paste.script.serve import ServeCommand

 from spawning import spawning_controller


 def config_factory(args):
+    pvalues, pargs = ServeCommand.parser.parse_args(args['args'])
+
     if 'config_url' in args:
         config_url = args['config_url']
         relative_to = args['relative_to']
         global_conf = args['global_conf']
     else:
-        config_file = os.path.abspath(args['args'][0])
+        config_file = os.path.abspath(pargs[0])
         config_url = 'config:%s' % (os.path.basename(config_file), )
         relative_to = os.path.dirname(config_file)
         global_conf = {}
-        for arg in args['args'][1:]:
+        for arg in pargs[1:]:
+            if '=' not in arg:
+                continue
             key, value = arg.split('=')
             global_conf[key] = value

     ctx = loadwsgi.loadcontext(
         loadwsgi.SERVER,
         config_url,
+        name=pvalues.server_name,
         relative_to=relative_to,
         global_conf=global_conf)

@@ -81,8 +87,11 @@ def config_factory(args):


 def app_factory(config):
+    pvalues, pargs = ServeCommand.parser.parse_args(config['args'])
+
     return loadwsgi.loadapp(
         config['config_url'],
+        name=pvalues.app_name,
         relative_to=config['relative_to'],
         global_conf=config['global_conf'])

@@ -93,10 +102,14 @@ def server_factory(global_conf, host, port, *args, **kw):

     def run(app):
         args = spawning_controller.DEFAULTS.copy()
-        args.update(
-            {'config_url': config_url, 'relative_to': relative_to, 'global_conf': global_conf})
-
-        spawning_controller.run_controller(
-            'spawning.paste_factory.config_factory', args)
+        args.update({
+            'config_url': config_url,
+            'relative_to': relative_to,
+            'global_conf': global_conf,
+            'args': sys.argv[1:],
+        })
+
+        spawning_controller.start_controller(
+            None, 'spawning.paste_factory.config_factory', args)

     return run
diff --git a/spawning/spawning_controller.py b/spawning/spawning_controller.py
index 8f17c32..7a1daea 100644
--- a/spawning/spawning_controller.py
+++ b/spawning/spawning_controller.py
@@ -138,7 +138,7 @@ class Controller(object):
                     str(child_side),
                     self.factory,
                     json.dumps(self.args)]
-                if self.args['reload'] == 'dev':
+                if self.args.get('reload') == 'dev':
                     command.append('--reload')
                 env = environ()
                 tpool_size = int(self.config.get('threadpool_workers', 0))
Author: @sayap Posted at: 12.08.2012 00:31 With the following diff, I can get `paster serve` to work fine with Spawning. The first 2 hunks add support for `--app-name` and `--server-name`, while the last 2 hunks unbreak support for `use = egg:Spawning`. I got lazy with arguments parsing, so I just pull in PasteScript as another dependency on top of PasteDeploy. Note that I have only done minimal testing with this... ``` diff diff --git a/spawning/paste_factory.py b/spawning/paste_factory.py index 0442652..cf89efb 100644 --- a/spawning/paste_factory.py +++ b/spawning/paste_factory.py @@ -24,27 +24,33 @@ import os import sys from paste.deploy import loadwsgi +from paste.script.serve import ServeCommand from spawning import spawning_controller def config_factory(args): + pvalues, pargs = ServeCommand.parser.parse_args(args['args']) + if 'config_url' in args: config_url = args['config_url'] relative_to = args['relative_to'] global_conf = args['global_conf'] else: - config_file = os.path.abspath(args['args'][0]) + config_file = os.path.abspath(pargs[0]) config_url = 'config:%s' % (os.path.basename(config_file), ) relative_to = os.path.dirname(config_file) global_conf = {} - for arg in args['args'][1:]: + for arg in pargs[1:]: + if '=' not in arg: + continue key, value = arg.split('=') global_conf[key] = value ctx = loadwsgi.loadcontext( loadwsgi.SERVER, config_url, + name=pvalues.server_name, relative_to=relative_to, global_conf=global_conf) @@ -81,8 +87,11 @@ def config_factory(args): def app_factory(config): + pvalues, pargs = ServeCommand.parser.parse_args(config['args']) + return loadwsgi.loadapp( config['config_url'], + name=pvalues.app_name, relative_to=config['relative_to'], global_conf=config['global_conf']) @@ -93,10 +102,14 @@ def server_factory(global_conf, host, port, *args, **kw): def run(app): args = spawning_controller.DEFAULTS.copy() - args.update( - {'config_url': config_url, 'relative_to': relative_to, 'global_conf': global_conf}) - - spawning_controller.run_controller( - 'spawning.paste_factory.config_factory', args) + args.update({ + 'config_url': config_url, + 'relative_to': relative_to, + 'global_conf': global_conf, + 'args': sys.argv[1:], + }) + + spawning_controller.start_controller( + None, 'spawning.paste_factory.config_factory', args) return run diff --git a/spawning/spawning_controller.py b/spawning/spawning_controller.py index 8f17c32..7a1daea 100644 --- a/spawning/spawning_controller.py +++ b/spawning/spawning_controller.py @@ -138,7 +138,7 @@ class Controller(object): str(child_side), self.factory, json.dumps(self.args)] - if self.args['reload'] == 'dev': + if self.args.get('reload') == 'dev': command.append('--reload') env = environ() tpool_size = int(self.config.get('threadpool_workers', 0)) ```
Sign in to join this conversation.
No Label
defect
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: rtyler/chucktesta#18
No description provided.