Merge branch 'test'

This commit is contained in:
Ian Adam Naval 2015-03-02 12:29:11 -05:00
commit 26529fe5a1
14 changed files with 146 additions and 25 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
__pycache__
*.pyc
*.egg-info

44
README.md Normal file
View File

@ -0,0 +1,44 @@
psh
===
Augmented Unix Userland shell inspired by Windows PowerShell, written in Python.
Requirements
------------
* Python 3+
* pip
Installing
----------
Preferably, you would use a separate virtual env
```
pip install -r requirements.txt
pip install -e . # installs the 'psh' package in editable mode
```
Running
-------
From Python shell:
```
from psh.run import main
main()
```
From Unix shell:
```
python -m psh.run
```
Testing
-------
From Unix shell:
```
py.test
```

11
psh/__init__.py Normal file
View File

@ -0,0 +1,11 @@
from psh.commands import registered_cmds
# Import the exported commands
from psh.example_cmd import *
# Instantiate the registered commands
for name, cls in registered_cmds.items():
globals()[name] = cls()
# Only export the names of registered commands
__all__ = registered_cmds.keys()

View File

@ -38,9 +38,11 @@ class BaseCommand(object):
return cmd
registered_cmds = []
registered_cmds = {}
def register_cmd(cls):
"""Decorator for putting all of the commands in one nice place."""
registered_cmds.append(cls.__name__)
return cls
def register_cmd(name):
def decorator(cls):
"""Decorator for putting all of the commands in one nice place."""
registered_cmds[name] = cls
return cls
return decorator

View File

@ -2,10 +2,8 @@ import atexit
import code
import os
import readline
import shlex
from commands import registered_cmds
import example_cmd
from psh.commands import registered_cmds
DEFAULT_HISTORY_FILE = "~/.psh_history"
@ -24,9 +22,10 @@ def parse_cmd(potential_cmd):
if args:
args = args[1:]
if cmd_name not in registered_cmds:
return "RawCommand({})".format(shlex.split(potential_cmd))
return "RawCommand('{}')".format(potential_cmd)
else:
return "{0}({1})".format(cmd_name,str(args))
cls = registered_cmds[cmd_name].__name__
return "{0}({1})".format(cls, str(args))
def parse_cmds(raw_input_line):

View File

@ -1,8 +1,8 @@
from commands import BaseCommand, register_cmd
from psh.commands import BaseCommand, register_cmd
@register_cmd
class example_cmd(BaseCommand):
@register_cmd("example")
class Example(BaseCommand):
"""Simple command that just returns 'example' and 'command'. Does
nothing at all with the input."""
@ -13,13 +13,13 @@ class example_cmd(BaseCommand):
return output_generator
@register_cmd
class echo(BaseCommand):
@register_cmd("echo")
class Echo(BaseCommand):
"""Echoes anything from the command line arguments as well as input
from the previous command."""
def __init__(self, args):
super(echo, self).__init__()
def __init__(self, args=[]):
super(Echo, self).__init__()
self.args = args
def call(self,*args,**kwargs):
@ -30,4 +30,3 @@ class echo(BaseCommand):
for line in input_generator:
yield line
return output_generator

View File

@ -1,4 +1,4 @@
from commands import BaseCommand
from psh.commands import BaseCommand
class Printer(BaseCommand):

View File

@ -1,5 +1,7 @@
from formatters import Printer
from commands import BaseCommand
import shlex
from psh.formatters import Printer
from psh.commands import BaseCommand
class RawCommand(BaseCommand):
@ -15,7 +17,7 @@ class RawCommand(BaseCommand):
input_generator = self.get_input_generator()
import subprocess
try:
p = subprocess.Popen(self.cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p = subprocess.Popen(shlex.split(self.cmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def make_output_generator():
input_str = b""
for line in input_generator:

View File

@ -1,8 +1,10 @@
import os
import os.path
from formatters import *
from raw_commands import RawCommand
from psh.formatters import *
from psh.example_cmd import Echo, Example
from psh.raw_commands import RawCommand
# Load all of the commands in the path into the global namespace as raw
# commands.
@ -15,7 +17,7 @@ for path in os.environ['PATH'].split(':'):
def main():
from console import HistoryConsole
from psh.console import HistoryConsole
console = HistoryConsole(globals())
console.interact("Augmented Unix Userland")

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pytest

20
setup.py Normal file
View File

@ -0,0 +1,20 @@
import os
from setuptools import setup
# Utility function to read the README file.
# Used for the long_description. It's nice, because now 1) we have a top level
# README file and 2) it's easier to type in the README file than to put a raw
# string in below ...
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(
name = "psh",
version = "0.0.1",
author = "WPI Augmented Unix Userland MQP",
author_email = "jsh@wpi.edu",
description = ("Simple Unix shell inspired by PowerShell"),
license = "MIT",
packages=['psh'],
long_description=read('README.md'),
)

19
test/test_example_cmd.py Normal file
View File

@ -0,0 +1,19 @@
import pytest
from psh import echo, example
from utils import TestFormatter
@pytest.fixture
def test_formatter():
return TestFormatter()
def test_example_cmd_should_return_two_things(test_formatter):
example.chain(test_formatter).call()
assert "examplecommand" == test_formatter.get_data()
def test_echo_should_echo(test_formatter):
example.chain(echo).chain(test_formatter).call()
assert "examplecommand" == test_formatter.get_data()

21
test/utils.py Normal file
View File

@ -0,0 +1,21 @@
from psh.commands import BaseCommand
from io import StringIO
class TestFormatter(BaseCommand):
"""Formatter useful for tests. Instead of printing to stdout, it
stores any output inside a stringio buffer. This can be retrieved
with the get_data method."""
def __init__(self, *args, **kwargs):
super(TestFormatter, self).__init__(*args, **kwargs)
self.buffer = StringIO()
def call(self):
input_generator = self.get_input_generator()
for line in input_generator:
self.buffer.write(line.decode('utf-8'))
return None
def get_data(self):
return self.buffer.getvalue()