Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

docs

  • Loading branch information...
commit 42b1e5e2fd8e7e0fe935318244e6d23c61ca7297 1 parent 0e72929
@tomerfiliba authored
View
154 README.rst
@@ -1,106 +1,84 @@
Plumbum: Shell Combinators
==========================
-Ever wished the wrist-handiness of shell scripts be put into a real language? Say hello to
-*Plumbum Shell Combinators*. Plumbum (Latin for *lead*, which was used to create pipes back
-in the day) is a small yet feature-rich library for shell script-like programs in Python.
-The motto of the library is you'd *never have to resort to shell scripts again*, and thus it
-attempts to mimic the shell syntax (but only where it makes sense) while keeping it cross-platform.
-
-Apart from shell-like syntax and nifty shortcuts, the library focuses on local and
-remote command execution, local and remote *paths*, and working directory and environment
-manipulation. But enough with the talk, let's see some code!
+Ever wished the wrist-handiness of shell scripts be put into a **real** programming language?
+Say hello to *Plumbum Shell Combinators*. Plumbum (Latin for *lead*, which was used to create
+pipes back in the day) is a small yet feature-rich library for shell script-like programs in Python.
+The motto of the library is **"Never write shell scripts again"**, and thus it attempts to mimic
+the **shell syntax** ("shell combinators") where it makes sense, while keeping it all **pythonic
+and cross-platform**.
+
+Apart from shell-like syntax and handy shortcuts, the library provides local and remote command
+execution (over SSH), local and remote file-system paths, easy working-directory and environment
+manipulation, and a programmatic Command-Line Interface (CLI) application toolkit.
+Now let's see some code!
*This is only a teaser; the full documentation can be found at*
`Read the Docs <http://plumbum.readthedocs.org>`_
-Basic Usage
+Cheat Sheet
-----------
-::
- >>> from plumbum import local
- >>> from plumbum.local import ls, grep, cat, wc
- >>>
+**Basics** ::
+
+ >>> from plumbum import local, FG, BG
+ >>> from plumbum.cmd import ls, grep, wc, cat, head
+ >>> ls
+ LocalCommand(<LocalPath /bin/ls>)
>>> ls()
- 'LICENSE\nREADME.rst\ndist\ndocs\nplumbum\n[...]'
- >>>
- >>> chain = ls | wc["-l"]
+ u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
+
+**Piping** ::
+
+ >>> chain = ls["-a"] | grep["-v", "\\.py"] | wc["-l"]
>>> print chain
- (C:\Program Files\Git\bin\ls.exe | C:\Program Files\Git\bin\wc.exe '-l')
+ /bin/ls -a | /bin/grep -v '\.py' | /usr/bin/wc -l
>>> chain()
- '9\n'
- >>> notepad = local["c:\\windows\\notepad.exe"]
- >>> notepad()
- ''
-
-Foregound and Background
-------------------------
-::
-
- >>> from plumbum import FG, BG
- >>> ls["-l"] & FG
- total 10
- -rw-r--r-- 1 sebulba Administ 1079 Apr 29 15:34 LICENSE
- -rw-r--r-- 1 sebulba Administ 1318 Apr 29 16:56 README.rst
- drwxr-xr-x 2 sebulba Administ 0 Apr 29 16:59 dist
- drwxr-xr-x 5 sebulba Administ 4096 Apr 29 23:38 docs
- drwxr-xr-x 2 sebulba Administ 4096 Apr 29 16:52 plumbum
- [...]
- >>> (ls["-a"] | wc["-l"]) & BG
- <Future ['C:\\Program Files\\Git\\bin\\wc.exe', '-l'] (running)>
- >>> f=_
- >>> f.wait()
- >>> f.stdout
- '16\n'
-
-Working Directory and Environment
----------------------------------
-::
+ u'13\n'
- >>> with local.cwd("c:\\windows"):
- ... (ls | wc["-l"])()
- ...
- '105\n'
- >>>
- >>> with local.env(FOO="BAR"):
- ... with local.env(FOO="SPAM"):
- ... local.python("-c", "import os;print os.environ['FOO']")
- ... local.python("-c", "import os;print os.environ['FOO']")
- ...
- 'SPAM\r\n'
- 'BAR\r\n'
+**Redirection** ::
-Remote Execution (over SSH)
----------------------------
-::
+ >>> ((cat < "setup.py") | head["-n", 4])()
+ u'#!/usr/bin/env python\nimport os\n\ntry:\n'
+ >>> (ls["-a"] > "file.list")()
+ u''
+ >>> (cat["file.list"] | wc["-l"])()
+ u'17\n'
- >>> from plumbum import Remote
- >>> r = Remote.connect("linuxbox.foo.bar")
- >>> r["uname"]()
- 'Linux\n'
- >>> r_ls = r["ls"]
- >>> r_ls
- <SshCommand ssh://linuxbox.foo.bar /bin/ls>
- >>>
- >>> with r.cwd("/"):
- ... r_ls()
- ...
- 'bin\nboot\ncdrom\ndev\netc\nhome\ninitrd.img\n[...]'
+**Working-directory manipulation** ::
+
+ >>> local.cwd
+ <Workdir /home/tomer/workspace/plumbum>
+ >>> with local.cwd(local.cwd / "docs"):
+ ... chain()
+ ...
+ u'15\n'
+
+**Foreground and background execution** ::
-Tunneling (over SSH)
---------------------
-::
+ >>> (ls["-a"] | grep["\\.py"]) & FG # The output is printed to stdout directly
+ build.py
+ .pydevproject
+ setup.py
+ >>> (ls["-a"] | grep["\\.py"]) & BG # The process runs "in the background"
+ <Future ['/bin/grep', '\\.py'] (running)>
+
+**Command nesting** ::
+
+ >>> from plumbum.cmd import sudo
+ >>> print sudo[ifconfig["-a"]]
+ /usr/bin/sudo /sbin/ifconfig -a
+ >>> (sudo[ifconfig["-a"]] | grep["-i", "loop"]) & FG
+ lo Link encap:Local Loopback
+ UP LOOPBACK RUNNING MTU:16436 Metric:1
- >>> r_python = r["python"]
- >>> f = (r_python["-c", "import socket;s=socket.socket();s.bind(('localhost',16666));" +
- ... "s.listen(1);s2=s.accept()[0];s2.send('great success')"] & BG
- >>> with r.sshctx.tunnel(12222, 16666) as tun:
- ... import socket
- ... s=socket.socket()
- ... s.connect(("localhost",12222))
- ... s.recv(100)
- ...
- 'great success'
- >>> f.ready()
- True
+**Remote commands (over SSH)** ::
+
+ >>> from plumbum import SshMachine
+ >>> remote = SshMachine("your-host.com")
+ >>> r_ls = remote["ls"]
+ >>> with remote.cwd("/lib"):
+ ... (r_ls | grep["0.so.0"])()
+ ...
+ u'libusb-1.0.so.0\nlibusb-1.0.so.0.0.0\n'
View
BIN  docs/_static/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  docs/_static/logo2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
19 docs/conf.py
@@ -42,17 +42,17 @@
# General information about the project.
project = u'Plumbum Shell Combinators'
-copyright = u'%d, Tomer Filiba' % (time.gmtime().tm_year,)
+copyright = u'%d, Tomer Filiba, licensed under Attribution-ShareAlike 3.0' % (time.gmtime().tm_year,)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-from plumbum.version import version_string #, release_date
+from plumbum.version import version_string, release_date
version = version_string
# The full version, including alpha/beta/rc tags.
-release = version_string # + " / " + release_date
+release = version_string + " / " + release_date
autodoc_member_order = "bysource"
@@ -95,26 +95,27 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'default'
+#html_theme = 'default'
+html_theme = 'haiku'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-#html_theme_options = {}
+html_theme_options = {"full_logo" : True}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-#html_title = None
+html_title = "Plumbum: Shell Combinators"
# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
+html_short_title = ""
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-#html_logo = None
+html_logo = "_static/logo2.png"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -132,7 +133,7 @@
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
-#html_use_smartypants = True
+html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
View
82 docs/index.rst
@@ -1,22 +1,23 @@
Plumbum: Shell Combinators
==========================
-Ever wished the wrist-handiness of shell scripts be put into a *real* programming language?
+Ever wished the wrist-handiness of shell scripts be put into a **real** programming language?
Say hello to *Plumbum Shell Combinators*. Plumbum (Latin for *lead*, which was used to create
pipes back in the day) is a small yet feature-rich library for shell script-like programs in Python.
-The motto of the library is *"You'll never have to write shell scripts again"*, and thus it
-attempts to mimic the shell syntax where it makes sense, while keeping it all pythonic and
-cross-platform.
+The motto of the library is **"Never write shell scripts again"**, and thus it attempts to mimic
+the **shell syntax** ("shell combinators") where it makes sense, while keeping it all **pythonic
+and cross-platform**.
+
Apart from :ref:`shell-like syntax <guide-local-commands>` and :ref:`handy shortcuts <guide-utils>`,
-the library provides local and :ref:`remote <guide-remote-machines>` command execution (over *SSH*),
+the library provides local and :ref:`remote <guide-remote-machines>` command execution (over SSH),
local and remote file-system :ref:`paths <guide-paths>`, easy working-directory and
environment :ref:`manipulation <guide-local-machine>`, and a programmatic
-:ref:`guide-cli` application toolkit. Let's see some code!
+:ref:`guide-cli` application toolkit. Now let's see some code!
Cheat Sheet
-----------
-Basics ::
+**Basics** ::
>>> from plumbum import local, FG, BG
>>> from plumbum.cmd import ls, grep, wc, cat, head
@@ -25,7 +26,7 @@ Basics ::
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
-Piping ::
+**Piping** ::
>>> chain = ls["-a"] | grep["-v", "\\.py"] | wc["-l"]
>>> print chain
@@ -33,16 +34,7 @@ Piping ::
>>> chain()
u'13\n'
-Workign-directory manipulation ::
-
- >>> local.cwd
- <Workdir /home/tomer/workspace/plumbum>
- >>> with local.cwd(local.cwd / "docs"):
- ... chain()
- ...
- u'15\n'
-
-Output/Input Redirection ::
+**Redirection** ::
>>> ((cat < "setup.py") | head["-n", 4])()
u'#!/usr/bin/env python\nimport os\n\ntry:\n'
@@ -50,8 +42,17 @@ Output/Input Redirection ::
u''
>>> (cat["file.list"] | wc["-l"])()
u'17\n'
+
+**Working-directory manipulation** ::
+
+ >>> local.cwd
+ <Workdir /home/tomer/workspace/plumbum>
+ >>> with local.cwd(local.cwd / "docs"):
+ ... chain()
+ ...
+ u'15\n'
-Foreground and Background Execution ::
+**Foreground and background execution** ::
>>> (ls["-a"] | grep["\\.py"]) & FG # The output is printed to stdout directly
build.py
@@ -60,7 +61,7 @@ Foreground and Background Execution ::
>>> (ls["-a"] | grep["\\.py"]) & BG # The process runs "in the background"
<Future ['/bin/grep', '\\.py'] (running)>
-Command nesting ::
+**Command nesting** ::
>>> from plumbum.cmd import sudo
>>> print sudo[ifconfig["-a"]]
@@ -69,7 +70,7 @@ Command nesting ::
lo Link encap:Local Loopback
UP LOOPBACK RUNNING MTU:16436 Metric:1
-Remote commands (over SSH) ::
+**Remote commands (over SSH)** ::
>>> from plumbum import SshMachine
>>> remote = SshMachine("your-host.com")
@@ -80,31 +81,46 @@ Remote commands (over SSH) ::
u'libusb-1.0.so.0\nlibusb-1.0.so.0.0.0\n'
-Development
-===========
+Development and Installation
+============================
The library is developed on `github <https://github.com/tomerfiliba/plumbum>`_, and will happily
-accept `pull requests <http://help.github.com/send-pull-requests/>`_ from users.
-Please use the github's built-in `issue tracker <https://github.com/tomerfiliba/plumbum/issues>`_
-to report any problem you encounter or to request features. The library is released under the
-permissive `MIT license <https://github.com/tomerfiliba/plumbum/blob/master/LICENSE>`_.
-
-You can **download** the library from `PyPI <http://pypi.python.org/pypi/plumbum>`_, or
-``easy-install`` / ``pip install`` it directly.
+accept `patches <http://help.github.com/send-pull-requests/>`_ from users. Please use the github's
+built-in `issue tracker <https://github.com/tomerfiliba/plumbum/issues>`_ to report any problem
+you encounter or to request features. The library is released under the permissive `MIT license
+<https://github.com/tomerfiliba/plumbum/blob/master/LICENSE>`_.
+
+Plumbum supports **Python 2.5-3.2** (requires `six <http://pypi.python.org/pypi/six>`_) and has been
+tested on **Linux** and **Windows** machines. Any \*nix should work fine, but on Windows,
+you'll probably want to install a decent **binutils environment** and add it to your ``PATH``,
+such as `cygwin <http://www.cygwin.com/>`_ or `mingw <http://mingw.org/>`_ (comes bundled with
+`Git for Windows <http://msysgit.github.com/>`_). Note that for remote command execution,
+an openSSH-compatible client is required (bundled with *Git for Windows*), and a binutils
+environment is also expected on the host machine (namely commands like ``which``, ``ls``, etc.)
+
+You can **download** the library from `PyPI <http://pypi.python.org/pypi/plumbum>`_ (in a variety
+of formats), or ``easy-install`` / ``pip install`` it directly.
User Guide
==========
+The user guide covers most of the features of Plumbum, with lots of code-snippets to get you
+swimming in no time. It introduces the concepts and the "syntax" gradually, so it's recommended
+to read it in order.
+
.. toctree::
:maxdepth: 2
local_commands
local_machine
- paths
remote_machine
- cli
utils
-
+ cli
+
API Reference
=============
+The API reference (generated from the *docstrings* within the library) covers all of the
+exposed APIs of the library. Note that some "advance" features or function parameters are missing
+from the guide, so you might want to consult with the API reference in this cases.
+
.. toctree::
:maxdepth: 2
View
82 docs/local_commands.rst
@@ -23,24 +23,28 @@ a ``Command`` object, you can execute it like a normal function::
>>> ls("-a")
'.\n..\n.git\n.gitignore\n.project\n.pydevproject\nREADME.rst\n[...]'
-With just a touch of magic, you can *import* commands from the ``local`` object, like so::
+With just a touch of magic, you can *import* commands from the mock module ``cmd``, like so::
>>> from plumbum.cmd import grep, cat
>>> cat
<LocalCommand C:\Program Files\Git\bin\cat.exe>
.. note::
- There's no real module named ``plumbum.cmd``; it's just a dynamically-created "module",
- added directly into ``sys.modules``, which enabled the use of ``from plumbum.cmd import foo``.
- Trying to ``import plumbum.cmd`` is bound to fail.
+ There's no real module named ``plumbum.cmd``; it's a dynamically-created "module", injected
+ into ``sys.modules``, which enabled the use of ``from plumbum.cmd import foo``. Trying to
+ ``import plumbum.cmd`` is bound to fail.
-Note that underscores (``_``) will be replaced by hyphens (``-``), if the original version
-is not found. Therefore, in order to get ``apt-get``, you can import ``apt_get``, for convenience.
+ It is important to stress that ``from plumbum.cmd import foo`` translates to ``local["foo"]``
+ behind the scenes.
+
+If underscores (``_``) appear in the name, and the name cannot be found in the path as-is,
+the underscores will be replaced by hyphens (``-``) and the name will be looked up again.
+This allows you to import ``apt_get`` for ``apt-get``.
Pipelining
----------
In order to form pipelines and other chains, we must first learn to *bind arguments* to commands.
-As you've seen, *invoking* commands runs the program; by using square brackets (``__getitem__``),
+As you've seen, *invoking* a command runs the program; by using square brackets (``__getitem__``),
we can create bound commands::
>>> ls["-l"]
@@ -48,7 +52,12 @@ we can create bound commands::
>>> grep["-v", ".py"]
BoundCommand(<LocalCommand C:\Program Files\Git\bin\grep.exe>, ('-v', '.py'))
-Forming pipelines now is easy and straight-forwards, using ``|`` (bitwise-or)::
+You can think of bound commands as commands that "remember" their arguments. Creating a bound
+command does not run the program; in order to run it, you'll need to call (invoke) it,
+like so: ``ls["-l"]()`` (in fact, ``ls["-l"]()`` is equivalent to ``ls("-l")``).
+
+Now that we can bind arguments to commands, forming pipelines is easy and straight-forwards,
+using ``|`` (bitwise-or)::
>>> chain = ls["-l"] | grep[".py"]
>>> print chain
@@ -57,11 +66,11 @@ Forming pipelines now is easy and straight-forwards, using ``|`` (bitwise-or)::
>>> chain()
'-rw-r--r-- 1 sebulba Administ 0 Apr 27 11:54 setup.py\n'
-Output/Input Redirection
+Input/Output Redirection
------------------------
We can also use redirection into files (or any object that exposes a real ``fileno()``).
If a string is given, it is assumed to be a file name, and a file with that name is opened
-for you. In this example, we're reading from ``stdin`` into ``grep world``, and redirect
+for you. In this example, we're reading from ``stdin`` into ``grep world``, and redirecting
the output to a file named ``tmp.txt``::
>>> import sys
@@ -69,7 +78,7 @@ the output to a file named ``tmp.txt``::
hello
hello world
what has the world become?
- foo
+ foo # Ctrl+D pressed
''
.. note::
@@ -114,6 +123,10 @@ one you passed::
Exit code: 1
Stderr: | "C:/Program Files/Git/bin/cat.exe": non/existing.file: No such file or directory
+.. note::
+ If you wish to accept several valid exit codes, ``retcode`` may be a tuple or a list.
+ For instance, ``grep("foo", "myfile.txt", retcode = (0, 2))``
+
Run and Popen
-------------
Notice that calling commands (or chained-commands) only returns their ``stdout``. In order to
@@ -123,21 +136,25 @@ a 3-tuple of the exit code, ``stdout``, and ``stderr``::
>>> ls.run("-a")
(0, '.\n..\n.git\n.gitignore\n.project\n.pydevproject\nREADME.rst\nplumbum\[...]', '')
-And, if you want to want to execute commands in the background (i.e., not wait for them to
+You can also pass ``retcode`` as a keyword argument to ``run`` in the same way discussed above.
+
+And, if you want to want to execute commands "in the background" (i.e., not wait for them to
finish), you can use the ``popen`` method, which returns a normal ``subprocess.Popen`` object::
>>> p = ls.popen("-a")
>>> p.communicate()
('.\n..\n.git\n.gitignore\n.project\n.pydevproject\nREADME.rst\nplumbum\n[...]', '')
+You can read from its ``stdout``, ``wait()`` for it, ``terminate()`` it, etc.
+
Background and Foreground
-------------------------
In order to make programming easier, there are two special objects called ``FG`` and ``BG``,
which are there to help you. ``FG`` runs programs in the foreground (they receive the parent's
``stdin``, ``stdout`` and ``stderr``), and ``BG`` runs programs in the background (much like
``popen`` above, but it returns a ``Future`` object, instead of a ``subprocess.Popen`` one).
-``FG`` is especially useful for interactive programs like editors, etc., that require a ``TTY``.
-::
+``FG`` is especially useful for interactive programs like editors, etc., that require a ``TTY``
+or input from the user. ::
>>> from plumbum import FG, BG
>>> ls["-l"] & FG
@@ -149,7 +166,7 @@ which are there to help you. ``FG`` runs programs in the foreground (they receiv
-rw-r--r-- 1 sebulba Administ 18 Apr 27 11:54 todo.txt
.. note::
- Note that the output of ``ls`` went straight to the screen
+ The output of ``ls`` went straight to the screen
::
@@ -162,4 +179,39 @@ which are there to help you. ``FG`` runs programs in the foreground (they receiv
>>> f.stdout
'.\n..\n.git\n.gitignore\n.project\n.pydevproject\nREADME.rst\nplumbum\n[...]'
+Nesting Commands
+----------------
+The arguments of commands can be strings (or any object that can convert to a string),
+as we've seen above, but they can also be **commands**! This allows for nesting commands into
+one another, forming complex command objects. The classic example is ``sudo``::
+
+ >>> from plumbum.cmd import sudo
+ >>> print sudo[ls["-l", "-a"]]
+ /usr/bin/sudo /bin/ls -l -a
+ u'total 22\ndrwxr-xr-x 8 sebulba Administ 4096 May 9 20:46 .\n[...]'
+
+In fact, you can nest even command-chains (i.e., pipes and redirections), e.g.,
+``sudo[ls | grep["\\.py"]]``; however, that would require that the top-level program be able to
+handle these shell operators, and this is not the case for ``sudo``. ``sudo`` expects its argument
+to be an executable program, and it would complain about ``|`` not being one. So, there's
+a inherent differnce between between ``sudo[ls] | grep["\\.py"]`` and
+``sudo[ls | grep["\\.py"]]`` -- the first one would fail, the second would work.
+
+Some programs, mostly shells, will be able to handle pipes and redirections -- an example of
+such a program is ``ssh``. For instance, you could run ``ssh["somehost", ls | grep["\\.py"]]()``;
+here, both ``ls`` and ``grep`` would run on ``somehost``, and only the filtered output would be
+sent (over SSH) to our machine. On the other hand, an invocation such as
+``(ssh["somehost", ls] | grep["\\.py"])()`` would run ``ls`` on ``somehost``, send its output to
+our machine, and ``grep`` would filter it locally.
+
+We'll learn more about remote command execution :ref:`later <guide-remote-commands>`. In the
+meanwhile, it's more useful to learn that command nesting works by *shell-quoting* (or
+*shell-escaping*) the nested command. Quoting normally takes place from the second level of
+nesting::
+
+ >>> print ssh["somehost", ssh["anotherhost", ls | grep["\\.py"]]]
+ /bin/ssh somehost /bin/ssh anotherhost /bin/ls '|' /bin/grep "'\\.py'"
+
+As you can see, ``|`` and the backslashes have been quoted, to prevent them from executing on
+the first-level shell; this way, they would safey get to the second-level shell.
View
67 docs/local_machine.rst
@@ -3,18 +3,10 @@
The Local Object
================
So far we've only seen running local commands, but there's more to the ``local`` object than
-this; it aims to represent the *local machine*, and it provides several useful APIs.
+this; it aims to "fully represent" the *local machine*.
-First, you should get acquainted with ``python``, which is a command object that points to
-the current interpreter (i.e., ``sys.executable``)::
-
- >>> local.python
- <LocalCommand c:\python27\python.exe>
- >>> local.python("-c", "import sys;print sys.version")
- '2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]\r\n'
-
-Another useful member is ``which``, which performs program name resolution in the executable
-``PATH`` (returns the first match, or raises an exception if no match is found)::
+First, you should get acquainted with ``which``, which performs program name resolution in
+the system ``PATH`` and returns the first match (or raises an exception if no match is found)::
>>> local.which("ls")
<LocalPath C:\Program Files\Git\bin\ls.exe>
@@ -23,8 +15,13 @@ Another useful member is ``which``, which performs program name resolution in th
[...]
plumbum.commands.CommandNotFound: ('nonexistent', [...])
-Yet another is ``tempdir``
+Another member is ``python``, which is a command object that points to the current interpreter
+(``sys.executable``)::
+ >>> local.python
+ <LocalCommand c:\python27\python.exe>
+ >>> local.python("-c", "import sys;print sys.version")
+ '2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]\r\n'
Working Directory
-----------------
@@ -51,14 +48,14 @@ But a much more useful pattern is to use it as a *context manager*, so it behave
Environment
-----------
-Similarly to ``cwd``, ``local.env`` represents the local environment. It is a dictionary-like
-object that holds the environment variables, which you can get/set intuitively::
+Much like ``cwd``, ``local.env`` represents the *local environment*. It is a dictionary-like
+object that holds **environment variables**, which you can get/set intuitively::
>>> local.env["JAVA_HOME"]
'C:\\Program Files\\Java\\jdk1.6.0_20'
>>> local.env["JAVA_HOME"] = "foo"
-And like ``cwd`` again, you can work with ``env`` as a context manager; each level would have
+And similarity to ``cwd`` is the context-manager nature of ``env``; each level would have
it's own private copy of the environment::
>>> with local.env(FOO="BAR"):
@@ -97,3 +94,43 @@ properties for getting the username (``.user``), the home path (``.home``), and
>>> local.env.path.insert(0, "c:\\python32")
>>> local.which("python")
<Path c:\python32\python.exe>
+
+.. _guide-paths:
+
+Local Paths
+===========
+Apart from commands, Plumbum provides an easy to use path class that represents file system paths.
+You've already seen paths; for instance, ``local.cwd`` is one, and so is the result of
+``local.which``. Paths are created by :func:`local.path() <platform.local_machine.LocalMachine.path>`,
+and you can join paths using ``/`` (division), perform globbing using ``//`` (floor division),
+iterate over the files and subdirectories contained in a directory, read and write file contents,
+etc. ::
+
+ >>> p = local.path("c:\\windows")
+ >>> p.exists()
+ True
+ >>> p.isdir()
+ True
+ >>> p.isfile()
+ False
+ >>> p / "notepad.exe"
+ <LocalPath c:\windows\notepad.exe>
+ >>> (p / "notepad.exe").isfile()
+ True
+ >>> for p2, _ in zip(p, range(3)):
+ ... print p2
+ ...
+ c:\windows\addins
+ c:\windows\appcompat
+ c:\windows\apppatch
+ >>> p // "*.dll"
+ [<LocalPath c:\windows\masetupcaller.dll>, ...]
+ >>> p // "*/*.dll"
+ [<LocalPath c:\windows\apppatch\acgenral.dll>, ...]
+ >>> local.cwd / "docs" // "*.rst"
+ [<LocalPath d:\workspace\plumbum\docs\cli.rst>, ...]
+
+If you need to **copy**, **move**, or **delete** paths, see the :ref:`utils modules <guide-utils>`
+
+
+
View
12 docs/paths.rst
@@ -1,12 +0,0 @@
-.. _guide-paths:
-
-Local Paths
-===========
-
-
-
-Remote Paths
-============
-
-
-
View
6 docs/remote_machine.rst
@@ -4,8 +4,14 @@ Remote Machines
===============
+.. _guide-remote-commands:
Remote Commands
===============
+.. _guide-remote-paths:
+
+Remote Paths
+============
+
View
32 docs/utils.rst
@@ -2,6 +2,32 @@
Utilities
=========
-copy
-move
-delete
+
+The ``utils`` module contains a collection of useful utility functions. Note that they are not
+imported into the namespace of ``plumbum`` directly, and you have to explicitly import them, e.g.
+``from plumbum.utils import copy``.
+
+* :func:`copy(src, dst) <plumbum.utils.copy>` - Copies ``src`` to ``dst`` (recursively, if ``src``
+ is a directory). The arguments can be either local or remote paths -- the function will sort
+ out all the necessary details.
+
+ * If both paths are local, the files are copied locally
+
+ * If one path is local and the other is remote, the function uploads/downloads the files
+
+ * If both paths refer to the same remote machine, the function copies the files locally on the
+ remote machine
+
+ * If both paths refer to different remote machines, the function downloads the files to a
+ temporary location and then uploads them to the destination
+
+* :func:`move(src, dst) <plumbum.utils.move>` - Moves ``src`` onto ``dst``. The arguments can be
+ either local or remote -- the function will sort our all the necessary details (as in ``copy``)
+
+* :func:`delete(*paths) <plumbum.utils.delete>` - Deletes the given sequence of paths; each path
+ may be a string, a local/remote path object, or an iterable of paths. If any of the paths does
+ not exist, the function silently ignores the error and continues. For example ::
+
+ from plumbum.utils import delete
+ delete(local.cwd // "*/*.pyc", local.cwd // "*/__pycache__")
+
Please sign in to comment.
Something went wrong with that request. Please try again.