Skip to content

Commit

Permalink
Convert to argparse
Browse files Browse the repository at this point in the history
Fixes #7
  • Loading branch information
jamadden committed Aug 18, 2017
1 parent d517a5a commit ee47754
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 44 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

- Fix the ``zpasswd`` console script on Python 3.

- Update the ``zpasswd`` script to use ``argparse`` instead of ``optparse.``

4.2.0 (2016-07-07)
==================

Expand Down
64 changes: 36 additions & 28 deletions src/zope/password/tests/test_zpasswd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import doctest
import os
import sys
import tempfile
import unittest

import io
Expand All @@ -36,13 +37,13 @@ class TestBase(unittest.TestCase):

def setUp(self):
# Create a minimal site.zcml file
with open('testsite.zcml', 'wb') as file:
file.write(
with tempfile.NamedTemporaryFile(prefix="testsite",
suffix=".zcml",
delete=False) as f:
f.write(
b'<configure xmlns="http://namespaces.zope.org/zope"/>\n')

def tearDown(self):
# Clean up
os.unlink('testsite.zcml')
self.config = f.name
self.addCleanup(os.remove, f.name)

@contextlib.contextmanager
def patched_stdio(self, input_data=None):
Expand Down Expand Up @@ -81,46 +82,52 @@ def patched_getpass(self, func):

class ArgumentParsingTestCase(TestBase):

config = "testsite.zcml"

def parse_args(self, args):
argv = ["foo/bar.py"] + args
with self.patched_stdio():
options = zpasswd.parse_args(argv)

self.assertEqual(options.program, "bar.py")
self.assertTrue(options.version)
return options

def check_stdout_content(self, args):
def check_stdout_content(self, args, stderr=False):
with self.assertRaises(SystemExit) as e:
self.parse_args(args)

e = e.exception
self.assertEqual(e.code, 0)
self.assertTrue(self.stdout.getvalue())
self.assertFalse(self.stderr.getvalue())
full = self.stdout
empty = self.stderr
if stderr:
full = self.stderr
empty = self.stdout
self.assertTrue(full.getvalue())
self.assertFalse(empty.getvalue())

def test_no_arguments(self):
options = self.parse_args([])
self.assertTrue(options.managers)
self.assertFalse(options.destination)
self.assertIs(options.destination, self.stdout)

def test_version_long(self):
self.check_stdout_content(["--version"])
self.check_stdout_content(["--version"],
stderr=sys.version_info[0] == 2)

def test_help_long(self):
self.check_stdout_content(["--help"])

def test_help_short(self):
self.check_stdout_content(["-h"])

def test_destination_short(self):
options = self.parse_args(["-o", "filename"])
self.assertEqual(options.destination, "filename")
def test_destination_short(self, option="-o"):
handle, path = tempfile.mkstemp()
os.close(handle)
self.addCleanup(os.remove, path)
options = self.parse_args([option, path])
self.assertEqual(options.destination.name, path)

def test_destination_long(self):
options = self.parse_args(["--output", "filename"])
self.assertEqual(options.destination, "filename")
self.test_destination_short("--output")

def test_config_short(self):
options = self.parse_args(["-c", self.config])
Expand All @@ -134,7 +141,7 @@ def test_too_many_arguments(self):
with self.assertRaises(SystemExit):
self.parse_args(["--config", self.config, "extra stuff"])

self.assertIn("too many arguments",
self.assertIn("unrecognized arguments",
self.stderr.getvalue())

def test_main(self):
Expand Down Expand Up @@ -163,11 +170,12 @@ def all_input_consumed(self):
class Options(object):

config = None
destination = None
version = "[test-version]"
program = "[test-program]"
managers = password.managers

def __init__(self):
self.destination = sys.stdout

class InputCollectionTestCase(TestBase):

def createOptions(self):
Expand All @@ -185,7 +193,6 @@ def _check_principal(self, expected, output=None):
self.assertEqual(line.strip(), expline)

def test_principal_information(self):
options = self.createOptions()
apps = []
def factory(options):
app = ControlledInputApplication(
Expand All @@ -195,6 +202,7 @@ def factory(options):
apps.append(app)
return app
with self.patched_stdio():
options = self.createOptions()
zpasswd.run_app_with_options(options, factory)
self.assertFalse(self.stderr.getvalue())
self.assertTrue(apps[0].all_input_consumed())
Expand All @@ -214,16 +222,16 @@ class TestDestination(InputCollectionTestCase):
destination = None

def createOptions(self):
import tempfile
opts = Options()
handle, destination = tempfile.mkstemp('.test_zpasswd')
self.addCleanup(lambda: os.remove(destination))
os.close(handle)
destination = tempfile.NamedTemporaryFile(mode='w',
suffix=".test_zpasswd",
delete=False)
self.addCleanup(os.remove, destination.name)
self.destination = opts.destination = destination
return opts

def _get_output(self):
with open(self.destination) as f:
with open(self.destination.name) as f:
return f.read()


Expand Down
30 changes: 14 additions & 16 deletions src/zope/password/zpasswd.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"""Implementation of the zpasswd script.
"""
from __future__ import print_function
import optparse
import argparse
import os
import sys
from xml.sax.saxutils import quoteattr
Expand Down Expand Up @@ -156,7 +156,7 @@ def read_password(self, prompt):
def process(self):
options = self.options

destination = sys.stdout if not options.destination else open(options.destination, 'w')
destination = options.destination
try:
principal = self.get_principal()

Expand Down Expand Up @@ -269,20 +269,18 @@ def get_password_managers(config_path=None):

def parse_args(argv):
"""Parse the command line, returning an object representing the input."""
_path, prog = os.path.split(os.path.realpath(argv[0]))
p = optparse.OptionParser(prog=prog,
usage="%prog [options]",
version=VERSION)
p.add_option("-c", "--config", dest="config", metavar="FILE",
help=("path to the site.zcml configuration file"
" (more accurate but slow password managers registry creation)"))
p.add_option("-o", "--output", dest="destination", metavar="FILE",
help=("the file in which the output will be saved"
" (STDOUT by default)"))
options, args = p.parse_args(argv[1:])
prog = os.path.split(os.path.realpath(argv[0]))[1]
p = argparse.ArgumentParser(prog=prog)
p.add_argument("-c", "--config", dest="config", metavar="FILE",
help=("path to the site.zcml configuration file"
" (more accurate but slow password managers registry creation)"))
p.add_argument("-o", "--output", dest="destination", metavar="FILE",
help=("the file in which the output will be saved"
" (STDOUT by default)"),
default=sys.stdout,
type=argparse.FileType('w'))
p.add_argument("--version", action="version", version=VERSION)
options = p.parse_args(argv[1:])
options.managers = get_password_managers(options.config)
options.program = prog
options.version = VERSION
if args:
p.error("too many arguments")
return options

0 comments on commit ee47754

Please sign in to comment.