Ian Bicking committed eb47554

Let silver run execute a script in any location, also silver run python will work, and ipython will be installed by default to allow interactive debugging

Comments (0)

Files changed (5)


 `` syncdb`` to get the tables in place.
 You can try ``silver serve .`` and go to ``/admin/`` to login and
-see your tables.  You might notice all the CSS is broken.  
+see your tables.  You might notice all the CSS is broken.
 Silver Lining serves static files out of the ``static/`` directory.
 You don't actually put ``static`` in the URLs, these files are
 use, it will be empty until you run ``syncdb``.  A good way to do that
-    $ silver run HOSTNAME syncdb
+    $ silver run HOSTNAME src/myapp/ syncdb
-This runs ``bin/`` on the host named ``HOSTNAME``.  You can
-use this for imports or other management tasks as well.
+You can use this for data imports or other management tasks as well.
 A more robust mechanism is to use the ``update_fetch`` setting in
 ``app.ini``: this is a URL (provided *by* your application) that is


 though they were local applications.  It looks like this::
      $ cd myapp-app
-     $ silver run import-script --setting=value ~/
+     $ silver run LOCATION import-script --setting=value ~/
 ``silver run`` takes as an argument the name of the script to run;
-this should be a script in the ``bin/`` directory (in this example
-``myapp-app/bin``) that has been uploaded to the server.  If you edit
-the file locally and don't do ``silver update`` remember that it will
-use the old version of the script.
+this should be a script that has been uploaded to the server (either a
+path relative to your app root, or a script in your app's ``bin/``
+directory).  If you edit the file locally and don't do ``silver
+update`` remember that it will use the old version of the script.
 The script must be a Python script.  The path will be appropriately
 setup so all your libraries will be ready, and environmental variables


         rest = [
             r.replace('$TMP', tmp_dir)
             for r in rest]
-    path = os.path.join(app_config.app_dir, 'bin', command)
+    path = find_command_path(app_config.app_dir, command)
+    check_command_python(path)
     os.environ['SILVER_VERSION'] = 'silverlining/0.0'
     sys.argv = [path] + rest
     ns = {'__file__': path, '__name__': '__main__'}
-    execfile(path, ns)
+    if os.path.basename(path) == 'ipython':
+        ## ipython-specific hack
+        if not os.access(os.environ['HOME'], os.W_OK):
+            os.environ['HOME'] = '/tmp'
+    os.chdir(app_config.app_dir)
+    if os.path.basename(path) in ('python', 'python2.6'):
+        from code import InteractiveConsole
+        console = InteractiveConsole()
+        console.interact()
+    else:
+        execfile(path, ns)
+def find_command_path(app_dir, command_name):
+    if command_name.startswith(os.path.sep):
+        # Absolute path
+        return command_name
+    places = [os.path.join(app_dir, 'bin'),
+              app_dir,
+              '/bin',
+              '/usr/bin']
+    for place in places:
+        place = os.path.join(place, command_name)
+        if os.path.exists(place):
+            return place
+    print >> sys.stderr, (
+        "%s not found (looked in %s)"
+        % (command_name, ', '.join(places)))
+    sys.exit(1000)
+def check_command_python(path):
+    if path.endswith('.py'):
+        # Good enough
+        return
+    if path.endswith('python') or path.endswith('python2.6'):
+        return
+    fp = open(path)
+    first = fp.readline()
+    fp.close()
+    if not first.startswith('#!'):
+        print >> sys.stderr, (
+            "Not a #! script: %s" % path)
+        sys.exit(1001)
+    if not 'python' in first:
+        print >> sys.stderr, (
+            "#! line in script is not for Python (%s): %s"
+            % (first.strip(), path))
+        sys.exit(1001)
 if __name__ == '__main__':


 remote server.
 Use it like:
-    silver run import-something --option-for-import-something
+    silver run LOCATION import-something --option-for-import-something
 Note any arguments that point to existing files or directories will
 cause those files/directories to be uploaded, and substituted with the
 location of the remote name.
+This will run *Python* scripts in your application's bin/ directory,
+in another directory (e.g., silver run LOCATION src/myapp/,
+or a global command (e.g., ipython).
+Use 'silver run LOCATION python' to get an interactive prompt on the
+remote server.


 zip	2.32-1