Skip to content

Commit 888e08f

Browse files
committed
Add click integration (closes #74)
This adds a custom parameter type that can be used with click options or arguments.
1 parent 4cdd6e0 commit 888e08f

File tree

7 files changed

+232
-2
lines changed

7 files changed

+232
-2
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ ci-unittests2:
212212
@echo "#############################################"
213213
. $(NAME)env2/bin/activate && export PYVER=PY2X && nosetests -v --with-coverage --cover-html --cover-min-percentage=90 --cover-package=bitmath tests/
214214
@echo "Testing argparse integration without progressbar dependency (#86)"
215-
. $(NAME)env2/bin/activate && pip uninstall -y progressbar231
215+
. $(NAME)env2/bin/activate && pip uninstall -y progressbar231 click
216216
. $(NAME)env2/bin/activate && export PYVER=PY2X && nosetests -v --with-coverage --cover-html --cover-min-percentage=90 --cover-package=bitmath tests/test_argparse_type.py
217217

218218
ci-list-deps2:
@@ -252,7 +252,7 @@ ci-unittests3:
252252
@echo "#############################################"
253253
. $(NAME)env3/bin/activate && export PYVER=PY3X && nosetests -v --with-coverage --cover-html --cover-package=bitmath tests/
254254
@echo "Testing argparse integration without progressbar dependency (#86)"
255-
. $(NAME)env3/bin/activate && pip uninstall -y progressbar33
255+
. $(NAME)env3/bin/activate && pip uninstall -y progressbar33 click
256256
. $(NAME)env3/bin/activate && export PYVER=PY3X && nosetests -v --with-coverage --cover-html --cover-package=bitmath tests/test_argparse_type.py
257257

258258
ci-list-deps3:

README.rst

+25
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ focusing on file size unit conversion, functionality now includes:
3333
* Reading a device's storage capacity (Linux/OS X support only)
3434
* `argparse <https://docs.python.org/2/library/argparse.html>`_
3535
integration as a custom type
36+
* `click <https://click.palletsprojects.com/>`_
37+
integration as a custom parameter type
3638
* `progressbar <https://code.google.com/p/python-progressbar/>`_
3739
integration as a better file transfer speed widget
3840
* String parsing
@@ -153,6 +155,7 @@ Topics include:
153155
* Context Managers
154156
* Module Variables
155157
* ``argparse`` integration
158+
* ``click`` integration
156159
* ``progressbar`` integration
157160

158161
* The ``bitmath`` command-line Tool
@@ -455,6 +458,28 @@ If ran as a script the results would be similar to this:
455458
$ python ./bmargparse.py --block-size 100MiB
456459
Parsed in: 100.0 MiB; Which looks like 819200.0 Kib as a Kibibit
457460
461+
``click`` Integration
462+
---------------------
463+
464+
Example script using ``bitmath.integrations.bmclick.BitmathType`` as an
465+
click parameter type:
466+
467+
.. code-block:: python
468+
469+
import click
470+
from bitmath.integrations.bmclick import BitmathType
471+
472+
@click.command()
473+
@click.argument('size', type=BitmathType())
474+
def best_prefix(size):
475+
click.echo(size.best_prefix())
476+
477+
If ran as a script the results should be similar to this:
478+
479+
.. code-block:: bash
480+
481+
$ python ./bestprefix.py "1024 KiB"
482+
1.0 MiB
458483
459484
``progressbar`` Integration
460485
---------------------------

bitmath/integrations/bmclick.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -*- coding: utf-8 -*-
2+
# The MIT License (MIT)
3+
#
4+
# Copyright © 2014-2016 Tim Bielawa <[email protected]>
5+
# See GitHub Contributors Graph for more information
6+
#
7+
# Permission is hereby granted, free of charge, to any person
8+
# obtaining a copy of this software and associated documentation files
9+
# (the "Software"), to deal in the Software without restriction,
10+
# including without limitation the rights to use, copy, modify, merge,
11+
# publish, distribute, sub-license, and/or sell copies of the Software,
12+
# and to permit persons to whom the Software is furnished to do so,
13+
# subject to the following conditions:
14+
#
15+
# The above copyright notice and this permission notice shall be
16+
# included in all copies or substantial portions of the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
# SOFTWARE.
26+
27+
import bitmath
28+
import click
29+
30+
31+
class BitmathType(click.ParamType):
32+
"""An parameter type for integrations with the click module.
33+
34+
For more information see https://click.palletsprojects.com/en/7.x/parameters/
35+
and https://click.palletsprojects.com/en/7.x/options/#basic-value-options
36+
37+
Example usage of the click Bitmath type for a click argument:
38+
39+
from bitmath.integrations.bmclick import BitmathType
40+
41+
@click.command()
42+
@click.argument('size', type=BitmathType)
43+
def best_prefix(size):
44+
click.echo(size.best_prefix())
45+
46+
It can also be used for click options:
47+
48+
from bitmath.integrations.bmclick import BitmathType
49+
50+
@click.command()
51+
@click.option('--size', required=True, type=BitmathType)
52+
def best_prefix(size):
53+
click.echo(size.best_prefix())
54+
"""
55+
name = 'bitmath'
56+
57+
def convert(self, value, param, ctx):
58+
try:
59+
return bitmath.parse_string(value)
60+
except ValueError:
61+
self.fail("'%s' can not be parsed into a valid bitmath object" %
62+
value)
63+
64+
65+
BITMATH = BitmathType()

docsite/source/index.rst

+24
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ focusing on file size unit conversion, functionality now includes:
2727
* Reading a device's storage capacity (Linux/OS X support only)
2828
* `argparse <https://docs.python.org/2/library/argparse.html>`_
2929
integration as a custom type
30+
* `click <https://click.palletsprojects.com/>`_
31+
integration as a custom parameter type
3032
* `progressbar <https://github.com/niltonvolpato/python-progressbar>`_
3133
integration as a better file transfer speed widget
3234
* String parsing
@@ -410,6 +412,28 @@ If ran as a script the results would be similar to this:
410412
$ python ./bmargparse.py --block-size 100MiB
411413
Parsed in: 100.0 MiB; Which looks like 819200.0 Kib as a Kibibit
412414
415+
``click`` Integration
416+
---------------------
417+
418+
Example script using ``bitmath.integrations.bmclick.BitmathType`` as an
419+
click parameter type:
420+
421+
.. code-block:: python
422+
423+
import click
424+
from bitmath.integrations.bmclick import BitmathType
425+
426+
@click.command()
427+
@click.argument('size', type=BitmathType())
428+
def best_prefix(size):
429+
click.echo(size.best_prefix())
430+
431+
If ran as a script the results should be similar to this:
432+
433+
.. code-block:: bash
434+
435+
$ python ./bestprefix.py "1024 KiB"
436+
1.0 MiB
413437
414438
``progressbar`` Integration
415439
---------------------------

requirements-py3.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ nose-cover3
66
pyflakes
77
pycodestyle
88
progressbar33
9+
click

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ nose
55
pyflakes
66
pycodestyle
77
progressbar231
8+
click

tests/test_click_type.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# -*- coding: utf-8 -*-
2+
# The MIT License (MIT)
3+
#
4+
# Copyright © 2014 Tim Bielawa <[email protected]>
5+
#
6+
# Permission is hereby granted, free of charge, to any person
7+
# obtaining a copy of this software and associated documentation files
8+
# (the "Software"), to deal in the Software without restriction,
9+
# including without limitation the rights to use, copy, modify, merge,
10+
# publish, distribute, sublicense, and/or sell copies of the Software,
11+
# and to permit persons to whom the Software is furnished to do so,
12+
# subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be
15+
# included in all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
# SOFTWARE.
25+
26+
27+
"""
28+
Test the click 'Bitmath' type integration
29+
"""
30+
31+
from . import TestCase
32+
import bitmath
33+
from bitmath.integrations.bmclick import BitmathType, BITMATH
34+
import click
35+
from click.testing import CliRunner
36+
37+
38+
class TestClickType(TestCase):
39+
def setUp(self):
40+
self.runner = CliRunner()
41+
42+
def test_click_BitmathType_good_one_arg(self):
43+
@click.command()
44+
@click.argument('arg', type=BitmathType())
45+
def func(arg):
46+
click.echo(arg)
47+
48+
result = self.runner.invoke(func, ['1000EB'])
49+
self.assertFalse(result.exception)
50+
self.assertEqual(result.output.splitlines(), [str(bitmath.EB(1000))])
51+
52+
def test_click_BitmathType_good_one_opt(self):
53+
@click.command()
54+
@click.option('--opt', type=BitmathType())
55+
def func(opt):
56+
click.echo(opt)
57+
58+
result = self.runner.invoke(func, ['--opt', '1007TB'])
59+
self.assertFalse(result.exception)
60+
self.assertEqual(result.output.splitlines(), [str(bitmath.TB(1007))])
61+
62+
def test_click_BitmathType_good_two_args(self):
63+
@click.command()
64+
@click.argument('arg1', type=BitmathType())
65+
@click.argument('arg2', type=BitmathType())
66+
def func(arg1, arg2):
67+
click.echo(arg1)
68+
click.echo(arg2)
69+
70+
result = self.runner.invoke(func, ['1337B', '0.001GiB'])
71+
self.assertFalse(result.exception)
72+
self.assertEqual(result.output.splitlines(), [str(bitmath.Byte(1337)),
73+
str(bitmath.GiB(0.001))])
74+
75+
def test_click_BitmathType_bad_wtfareyoudoing(self):
76+
@click.command()
77+
@click.argument('arg', type=BitmathType())
78+
def func(arg):
79+
click.echo(arg)
80+
81+
result = self.runner.invoke(func, ['2098329324kdsjflksdjf'])
82+
self.assertTrue(result.exception)
83+
84+
def test_click_BitmathType_good_spaces_in_value(self):
85+
@click.command()
86+
@click.argument('arg1', type=BitmathType())
87+
@click.argument('arg2', type=BitmathType())
88+
def func(arg1, arg2):
89+
click.echo(arg1)
90+
click.echo(arg2)
91+
92+
result = self.runner.invoke(func, ['100 MiB', '200 KiB'])
93+
self.assertFalse(result.exception)
94+
self.assertEqual(result.output.splitlines(), [str(bitmath.MiB(100)),
95+
str(bitmath.KiB(200))])
96+
97+
def test_click_BitmathType_bad_spaces_in_value(self):
98+
@click.command()
99+
@click.argument('arg', type=BitmathType())
100+
def func(arg):
101+
click.echo(arg)
102+
103+
result = self.runner.invoke(func, ['1000', 'EB'])
104+
self.assertTrue(result.exception)
105+
106+
def test_click_BITMATH_good_one_arg(self):
107+
@click.command()
108+
@click.argument('arg', type=BITMATH)
109+
def func(arg):
110+
click.echo(arg)
111+
112+
result = self.runner.invoke(func, ['1234.5 TiB'])
113+
self.assertFalse(result.exception)
114+
self.assertEqual(result.output.splitlines(), [str(bitmath.TiB(1234.5))])

0 commit comments

Comments
 (0)