Giter Club home page Giter Club logo

plumbum's Introduction

Documentation Status

Build Status

Coverage Status

PyPI Status

PyPI Versions

Conda-Forge Badge

PyPI License

Join the chat at https://gitter.im/plumbumpy/Lobby

Code styled with Black

Plumbum: Shell Combinators

Ever wished the compactness 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

Cheat Sheet

Basics

>>> from plumbum import local
>>> local.cmd.ls
LocalCommand(/bin/ls)
>>> local.cmd.ls()
'build.py\nCHANGELOG.rst\nconda.recipe\nCONTRIBUTING.rst\ndocs\nexamples\nexperiments\nLICENSE\nMANIFEST.in\nPipfile\nplumbum\nplumbum.egg-info\npytest.ini\nREADME.rst\nsetup.cfg\nsetup.py\ntests\ntranslations.py\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
''                                              # Notepad window is closed by user, command returns

In the example above, you can use local["ls"] if you have an unusually named executable or a full path to an executable. The local object represents your local machine. As you'll see, Plumbum also provides remote machines that use the same API! You can also use from plumbum.cmd import ls as well for accessing programs in the PATH.

Piping

>>> from plumbum.cmd import ls, grep, wc
>>> chain = ls["-a"] | grep["-v", r"\.py"] | wc["-l"]
>>> print(chain)
/bin/ls -a | /bin/grep -v '\.py' | /usr/bin/wc -l
>>> chain()
'27\n'

Redirection

>>> from plumbum.cmd import cat, head
>>> ((cat < "setup.py") | head["-n", 4])()
'#!/usr/bin/env python3\nimport os\n\ntry:\n'
>>> (ls["-a"] > "file.list")()
''
>>> (cat["file.list"] | wc["-l"])()
'31\n'

Working-directory manipulation

>>> local.cwd
<LocalWorkdir /home/tomer/workspace/plumbum>
>>> with local.cwd(local.cwd / "docs"):
...     chain()
...
'22\n'

Foreground and background execution

>>> from plumbum import FG, BG
>>> (ls["-a"] | grep[r"\.py"]) & FG         # The output is printed to stdout directly
build.py
setup.py
translations.py
>>> (ls["-a"] | grep[r"\.py"]) & BG         # The process runs "in the background"
<Future ['/bin/grep', '\\.py'] (running)>

Command nesting

>>> from plumbum.cmd import sudo, ifconfig
>>> 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

Remote commands (over SSH)

Supports openSSH-compatible clients, PuTTY (on Windows) and Paramiko (a pure-Python implementation of SSH2)

>>> from plumbum import SshMachine
>>> remote = SshMachine("somehost", user = "john", keyfile = "/path/to/idrsa")
>>> r_ls = remote["ls"]
>>> with remote.cwd("/lib"):
...     (r_ls | grep["0.so.0"])()
...
'libusb-1.0.so.0\nlibusb-1.0.so.0.0.0\n'

CLI applications

import logging
from plumbum import cli

class MyCompiler(cli.Application):
    verbose = cli.Flag(["-v", "--verbose"], help = "Enable verbose mode")
    include_dirs = cli.SwitchAttr("-I", list = True, help = "Specify include directories")

    @cli.switch("--loglevel", int)
    def set_log_level(self, level):
        """Sets the log-level of the logger"""
        logging.root.setLevel(level)

    def main(self, *srcfiles):
        print("Verbose:", self.verbose)
        print("Include dirs:", self.include_dirs)
        print("Compiling:", srcfiles)

if __name__ == "__main__":
    MyCompiler.run()

Sample output

$ python3 simple_cli.py -v -I foo/bar -Ispam/eggs x.cpp y.cpp z.cpp
Verbose: True
Include dirs: ['foo/bar', 'spam/eggs']
Compiling: ('x.cpp', 'y.cpp', 'z.cpp')

Colors and Styles

from plumbum import colors
with colors.red:
    print("This library provides safe, flexible color access.")
    print(colors.bold | "(and styles in general)", "are easy!")
print("The simple 16 colors or",
      colors.orchid & colors.underline | '256 named colors,',
      colors.rgb(18, 146, 64) | "or full rgb colors",
      'can be used.')
print("Unsafe " + colors.bg.dark_khaki + "color access" + colors.bg.reset + " is available too.")

plumbum's People

Contributors

abarnert avatar acehreli avatar andydecleyre avatar asmfreak avatar astraw38 avatar chaoflow avatar closier avatar coroa avatar dependabot[bot] avatar fahhem avatar gschaffner avatar hashbrowncipher avatar hassium-269 avatar henryiii avatar kelbyers avatar kolanich avatar koreno avatar moskupols avatar multimeric avatar njharman avatar oakreid avatar r-darwish avatar smheidrich avatar swayf avatar tillberg avatar timgates42 avatar tomer-weka avatar tomerfiliba avatar unhandled-exception avatar vittyvk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plumbum's Issues

Background command blocks on stdout

A command set to run in the background (or with cmd.popen) will block after filling its stdout buffer until .wait() is called.

I'm not sure there is a way to fix this. Just adding a warning in the documentation might be the best that can be done.

Handle quoted empty string argument.

Trying to generate ssh keys:

keygen = local['ssh-keygen']
keygen('-t', 'rsa', '-N', '', '-f', 't_key.pub')

results in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/plumbum/commands.py", line 219, in __call__
    return self.run(args, **kwargs)[1]
  File "/usr/lib/python2.7/site-packages/plumbum/commands.py", line 275, in run
    return run_proc(p, retcode, timeout)
  File "/usr/lib/python2.7/site-packages/plumbum/commands.py", line 173, in run_proc
    stdout, stderr)
plumbum.commands.ProcessExecutionError: Command line: ['/usr/bin/ssh-keygen', '-t', 'rsa', '-N', '-f', 't_key.pub']
Exit code: 1
Stdout:  | Too many arguments.

i.e. the empty single quoted passphrase for -N is ignored.

Whereas the subprocess equivalent works as expected.

>>> com = ['ssh-keygen', '-t', 'rsa', '-N', '', '-f', 't_key.pub']
>>> r = subprocess.Popen(com, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> r.returncode
>>> (output, error) = r.communicate()
>>> r.returncode
0
>>> output
"Generating public/private rsa key pair.\nYour identification has been saved in t_key.pub.\nYour public key has been saved in t_key.pub.pub.\nThe key fingerprint is:\n16:28:94:a5:73:e0:56:1f:73:88:b1:86:e4:32:8a:28 [email protected]\nThe key's randomart image is:\n+--[ RSA 2048]----+\n|    +o+oo..      |\n|   =.=.+.+       |\n|  o O = o        |\n|o. + =   .       |\n|E       S        |\n|.      .         |\n|                 |\n|                 |\n|                 |\n+-----------------+\n"

local object accept a list?

The only examples I see are like:

ls = local['ls']

res = ls('some string')

But I need:

res = ls([some, list, of, args])

Implement API for "subcommand" style interfaces

Plumbum should provide an API for "subcommand" style interfaces, in which the cli app has a number of subcommands.

e.g. svn, hg, bzr, git, etc.

One way to do this might be to provide a cli.subcommand decorator which you would use to decorate functions in a cli.Application. Then the parsing logic would look for any of these and use whichever one was specified on the command line instead of the current main method.

Rethink encoding

The output of commands is treated like text strings... need a better way to differentiate between byte-level commands and text-level commands. Maybe local.text["ls"] vs. local.bytes["ls"] ?

Plumbum failing when run with Flask

Don't know who to blame but plumbum 1.1.0 fails to run in trivial combination with Flask 0.9 while plumbum 1.0.1 works well. Here is code to reproduce issue.
And here is output:

>python index.py 
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader
Traceback (most recent call last):
  File "index.py", line 12, in <module>
    app.run()
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/flask/app.py", line 739, in run
    run_simple(host, port, self, **options)
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/werkzeug/serving.py", line 615, in run_simple
    run_with_reloader(inner, extra_files, reloader_interval)
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/werkzeug/serving.py", line 533, in run_with_reloader
    reloader_loop(extra_files, interval)
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/werkzeug/serving.py", line 439, in _reloader_stat_loop
    for filename in chain(_iter_module_files(), extra_files or ()):
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/werkzeug/serving.py", line 413, in _iter_module_files
    filename = getattr(module, '__file__', None)
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/plumbum/local_machine.py", line 537, in __getitem__
    return LocalCommand(self.which(cmd))
  File "/home/user/pyenv/fplu/local/lib/python2.7/site-packages/plumbum/local_machine.py", line 508, in which
    raise CommandNotFound(progname, list(cls.env.path))
plumbum.commands.CommandNotFound: ('__file__', [<LocalPath /home/user/pyenv/fplu/bin>, <LocalPath /home/user/.pythonbrew/bin>, <LocalPath /home/user/.pythonbrew/bin>, <LocalPath /usr/local/bin>, <LocalPath /usr/bin>, <LocalPath /bin>, <LocalPath /usr/games>])

syntax change?

local['ls'] seems strange to me. I think local('ls') makes more sense - it looks like a constructor call.

remote: whitespaces in remote path results in "ambiguous target" error

code:

lpath = local.path('/var/ftp/deploy/images/current/') / target_vm // '*'
rpath = remote.path(datastore.summary.url) / target_vm
for path in lpath:
     print "lpath = '%s'" % path
     print "rpath = '%s'" % rpath
     remote.upload(path, rpath / path.basename)

output:

lpath = '/var/ftp/deploy/images/current/MgmtVM/MgmtVM.ovf'
rpath = '/vmfs/volumes/4f41cb66-5f5228fd-e818-001cc06d4ba7/Test Cloud 1 - Management'
Traceback (most recent call last):
  File "create-vm.py", line 181, in <module>
    remote.upload(path, rpath / path.basename)
  File "/usr/lib/python2.6/site-packages/plumbum/remote_machine.py", line 562, in upload
    self._scp_command(src, "%s:%s" % (self._fqhost, dst))
  File "/usr/lib/python2.6/site-packages/plumbum/commands.py", line 151, in __call__
    return self.run(args, **kwargs)[1]
  File "/usr/lib/python2.6/site-packages/plumbum/commands.py", line 201, in run
    return run_proc(p, retcode)
  File "/usr/lib/python2.6/site-packages/plumbum/commands.py", line 105, in run_proc
    proc.returncode, stdout, stderr)
plumbum.commands.ProcessExecutionError: Command line: ['/usr/bin/scp', '-r', '/var/ftp/deploy/images/current/MgmtVM/MgmtVM.ovf', '[email protected]:/vmfs/volumes/4f41cb66-5f5228fd-e818-001cc06d4ba7/Test Cloud 1 - Management/MgmtVM.ovf']
Exit code: 1
Stderr:  | scp: ambiguous target

feature request - daemon

I'm interested in using plumbum to start long-running simulations (replacing my own code that I use for this purpose). One feature I use is to start programs as daemons, so that they will not be killed by HUP. I usually build this into my client code:

if opt.daemon:
    from daemon import basic_daemonize
    basic_daemonize()

But it seems a nice, simple addition to plumbum 'run'. Along with, my own code will handle logging of stdout, stderr. Again, plumbum could handle this.

TypeError for unicode arguments

Using from __future__ import unicode_literals gives tons of errors due to explicit type checking of the form

if not isinstance(newdir, (str, LocalPath)):
    raise TypeError("newdir must be a string or a LocalPath, not %r" % (newdir,))

Could you either use basestring instead of str or, preferably, remove the explicit typechecks altogether? I'd be glad to send in a patch if you are willing to accept this change.

The removal of the checks would also allow the passing of objects that define a reasonable __str__ method according to "we are all consenting adults here".

Run local commands through local.popen

Instead of having the Popen code in LocalCommand, move it into local._popen or something. That way we could apply context managers on local commands, e.g.,

with local.as_user("foo"):
    ls()

(see also #9)

subprocess.STARTF_USESHOWWINDOW does not exist in python 2.7 on windows

When attempting to use plumbum with python 2.7 (32 bit) on windows 7 I receive the following error:

Traceback (most recent call last):
  File "D:\src\scripts\updatecg.py", line 17, in <module>
    net('stop', 'camgat')
  File "C:\Python27\lib\site-packages\plumbum\commands.py", line 151, in __call__
    return self.run(args, **kwargs)[1]
  File "C:\Python27\lib\site-packages\plumbum\commands.py", line 199, in run
    p = self.popen(args, **kwargs)
  File "C:\Python27\lib\site-packages\plumbum\local_machine.py", line 376, in popen
    kwargs["startupinfo"].dwFlags |= subprocess.STARTF_USESHOWWINDOW  #@UndefinedVariable
AttributeError: 'module' object has no attribute 'STARTF_USESHOWWINDOW'

Similarly, subprocess.SW_HIDE also doesn't exist in this version of python.

I have been able to fix this by using subprocess._subpprocess.STARTF_USESHOWWINDOW instead, though I'm not sure how cross platform this fix is.

Weirdness around "~"

This might be a bug??

from plumbum import local

machine = local
home = machine.path("~")
print home

Output:

/homes/harlowja/~

Maybe a special case is needed for "~"??

I would have expected /homes/harlowja/ and not /homes/harlowja/~

Walk doesn't use the filter recursively

In path.walk, the filter function is not passed recursively:

    for p in self.list():
        if filter(p):
            yield p
            if p.isdir():
                for p2 in p.walk(FILTERNEEDSTOGOHERE):
                    yield p2

SshMachine on windows with plink/pscp hangs in popen

>>> from plumbum import SshMachine
>>> from plumbum.cmd import plink, pscp
>>> rem = SshMachine('app5',ssh_command=plink,scp_command=pscp,ssh_opts=['-ssh'])
#
# wait then type ctrl+C
#
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\remote_machine.py", line 357, in __init__
    BaseRemoteMachine.__init__(self)
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\remote_machine.py", line 151, in __init__
    self._session = self.session()
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\remote_machine.py", line 381, in session
    return ShellSession(self.popen((), ["-tt"] if isatty else []), self.encoding, isatty)
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\session.py", line 132, in __init__
    self.run("")
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\session.py", line 213, in run
    return run_proc(self.popen(cmd), retcode)
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\commands.py", line 152, in run_proc
    stdout, stderr = proc.communicate()
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\session.py", line 91, in communicate
    line = pipe.readline()
  File "c:\python\lib\site-packages\plumbum-1.0.0-py2.7-win32.egg\plumbum\session.py", line 39, in readline
    line = self.pipe.readline()
KeyboardInterrupt
>>>

SSH user not passed on to paramiko

ParamikoMachine always tries to connect with default user, even if user arg is given to ParamikoMachine.__init__. This leads to login as the wrong user when e.g. SSH keys are available for multiple users to the same host.

suggested fix:

        if user is not None:
            kwargs["username"] = user

a shortcut to switch decorator with default

I have a parameter the get a comma separated list:

app --skip "A,B,C , D, F"

in my code I'm doing this:

    parsers_skip = []
    @switch("--skip")
    def skip(self, input):
        self.parsers_skip = [ i.strip() for i in input.split(',') ]

I'm looking for a shorter decorator for this, maybe making the autoswitch to accept a default
something like that :

    @autoswitch("--skip", default=[])
    def parsers_skip(self, input):
        return [ i.strip() for i in input.split(',') ]

I've looked into the code, but didn't thought of a way to implement it.
but that example is really DRY counter example (repeating the name of the switch three times)

shquote breaks certain sudo commands

Hi,
when using some sudo commands I found out that they were failing where they shouldn't have. E.g.:

from plumbum.cmd import sudo, yum

sudo(yum['install']['rubygem(rails)'])

This fails, because rubygem(rails) gets overquoted by formulate (which calls shquote). This ends up formulated like this:

['/usr/bin/sudo', '/usr/bin/yum', 'install', "'rubygem(rails)'"]

So yum in fact gets "'rubygem(rails)'" on commandline (because Popen puts the outer quotes there.

I think that the problem can be solved by adding '(' and ')' to _safechars, which seems ok to me, but I'm not sure of other consequences of this. Any other options how to solve this?

Thanks.

Cannot set value of SwitchAttr

It seems odd to me that you can't set the value of a SwitchAttr from within a CLI application.

Here's a simple test case:

from plumbum import cli

class MyApp(cli.Application):
    param = cli.SwitchAttr(['-p', '--param'], str, default='default')

    def main(self):

        if self.param == 'default':
            # then do some stuff here, like maybe get the value for param 
            # from a config file
            config_file_param = 'fromconfig'
            self.param = config_file_param


if __name__ == '__main__':
    MyApp.run()

which results in:

Traceback (most recent call last):
  File "temp.py", line 16, in <module>
    MyApp.run()
  File "C:\Documents and Settings\funsize\Desktop\plumbum_test\venv\lib\site-packages\plumbum\cli.py", line 541, in run
    _, retcode = cls._run(argv)
  File "C:\Documents and Settings\funsize\Desktop\plumbum_test\venv\lib\site-packages\plumbum\cli.py", line 532, in _run
    retcode = inst.main(*tailargs)
  File "temp.py", line 12, in main
    self.param = config_file_param
TypeError: __set__() takes exactly 4 arguments (3 given)

Looking at the code for SwitchAttr, it doesn't look like a regular descriptor to me (at least it doesn't seem to follow the descriptor protocol, but perhaps I'm missing something), so I confess I don't really understand how it's supposed to work, but it seems pretty strange to me.

At any rate, it would be pretty convenient to be able to set SwitchAttrs inside my App.

remote piping is misleading

remote: piping doesn't work as expected (it happens on the local host).
need a way to convert foo | bar to rem[foo | bar]

adding exit parameter to Application.run()

I suggest changing run to something like that:

    @classmethod
    def run(cls, argv = sys.argv, exit=True):
        """Runs the application, taking the arguments from ``sys.argv``, and exiting with the
        appropriate exit code; when ``exit`` is True this function does not return, else it return the return code """
        _, retcode = cls._run(argv)
        if exit:
            sys.exit(retcode)
        else:
            return retcode

it can help when unittesting or when invoking from other applications like that:

    def test_01_running_from_cmd_line(self):
        self.assertEqual(
            PostProcessor.run(['app', '-l', self.test_data, '-s', self.test_scripts], exit=False),
            0
        )

BTW, really nice package (got me to ditch pbs)

"from plumbum.cmd import" does not work on python 3.3

When trying to import any command in python 3.3 following exception occurs

>>> from plumbum.cmd import wc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1597, in _handle_fromlist
  File "/usr/lib/python3.3/site-packages/plumbum/local_machine.py", line 537, in __getitem__
    return LocalCommand(self.which(cmd))
  File "/usr/lib/python3.3/site-packages/plumbum/local_machine.py", line 508, in which
    raise CommandNotFound(progname, list(cls.env.path))
plumbum.commands.CommandNotFound: ('__path__', [<LocalPath /usr/local/bin>, <LocalPath /usr/bin>, <LocalPath /bin>, <LocalPath /usr/local/sbin>, <LocalPath /usr/sbin>, <LocalPath /sbin>, <LocalPath ~/bin>, <LocalPath /usr/bin/vendor_perl>, <LocalPath /usr/bin/core_perl>, <LocalPath /usr/lib/qt4/bin>, <LocalPath /home/blin/bin>, <LocalPath /home/blin/bin>])

This seems to be due to http://docs.python.org/3/whatsnew/3.3.html#importlib

What happens is that

__import__('plumbum.cmd', fromlist=('wc')

eventually calls

hasattr(plumbum.cmd, '__path__')

which calls

plumbum.local_machine.local.__getitem__('__path__').

which fails.

Proposed solution is to replace

__getattr__ = local.__getitem__

in cmd with

def __getattr__(self, name):
    if name != '__path__':
        return local.__getitem__(name)
    else:
        pass

help to be able to accept a list

just a cosmetically nice to have feature,

if help could accept a list and correctly indent the lines

    log_path = SwitchAttr(["-l", "--log-path"], argtype = str,
        help=["path to the log directory", "default to current directory"] )
...
  Switches:
    -l, --log-path VALUE:str   path to the log directory
                               default to current directory
...

paramiko error while installing on python 3.3

Hi! I really love the idea of this package (no shell anymore, what a bliss :) ) and will use it very soon. It installed without problems on python 2.7, but with python 3.3 gave me this error:

Installing collected packages: plumbum
Running setup.py install for plumbum
File "/usr/local/lib/python3.3/dist-packages/plumbum/paramiko_machine.py", line 64
print "!!", repr(line)
^
SyntaxError: invalid syntax

I installed it with:
sudo pip install -U plumbum
on a Ubuntu 12.10 machine

I've most of the locale class use cases and everything work smoothly, but have no remote machine to test so I'm not sure if the paramiko class really works or not.

Problem with unix line endings?

Tried 0.9.0, and also latest git. Same result. Seems that grep isn't understanding unix line endings?

In [4]: chain = ls["-1"] | grep[r"\.py"]
In [5]: chain()
Out[5]:
u'ave_freq_est.py\nave_freq_est.py~\nave_freq_est.pyc\nconst16apsk.py\nconst16apsk.pyc\nconstant_gen.py\nconstant_gen.pyc\nread_hist.py\nread_hist.py~\nsync_time.py\nsync_time.py~\ntest_ave_freq_est.py\ntest_ave_freq_est.py~\ntest_btr2.py\ntest_btr2.py~\ntest_conv.py\ntest_freq_est.py\ntest_uw_freq.py\ntest_uw_freq.py~\ntest_uw.py\ntest_uw.py~\n'

CLI: allow name to be inferred

@switch(argtype = str)
def log_to_file(self, filename):
    pass

==>

@switch("--log-to-file", argtype = str)
def log_to_file(self, filename):
    pass

Root mode context manager?

It might be useful to say do the following:

ls = local['ls'] (or use SshMachine here...)
with Root(ls) as root_ls:
    root_ls.run()

This way people can run as other users in a pythonic way (root show as an example here). Similarly the same would be neat with ssh/remote shells. Sometimes u just need to run a single command as another user (ie apt-get install) and u don't want the rest of the commands ran as that user... Thoughts?

Paths are always converted to lowercase on windows

I've been using plumbum paths in a script i'm writing lately. My script uses local.cwd to find out the name of the current directory, then uses that to navigate to a path on a remote PC.

Unfortunately the script doesn't work at all when the local machine is windows, the remote is linux and the current directory name is not all lowercase. This seems to be because plumbum throws away case information from paths on windows.

For example:

>>> import os
>>> from plumbum import local
>>> os.getcwd()
'C:\\src\\NVR'
>>> local.cwd.basename
'nvr'

If I then try to use local.cwd.basename to navigate to the equivalent folder on my remote PC it will fail as the folder is actually named NVR rather than nvr.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.