Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,9 @@
"editor.renderWhitespace": "all",
"editor.rulers": [ 76 ],
"editor.tabSize": 2,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"git.mergeEditor": false,
"files.exclude": {
"**/__pycache__": true,
"**/*.egg-info": true,
Expand Down
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
# **CLASP.Python** Changes <!-- omit from toc -->


## 0.8.12 - 28th July 2026

* fixed falsy default values causing `MissingValueException` for option arguments;
* fixed failure message to be passed to `MissingValueException`;


## 0.8.11 - 27th July 2026

* ~ packaging & boilerplate improvements:
Expand Down
2 changes: 1 addition & 1 deletion pyclasp/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
__license__ = "BSD-3-Clause"
__maintainer__ = "Matt Wilson"
__status__ = "Beta"
__version__ = "0.8.11"
__version__ = "0.8.12"

from .exceptions import *
from .flag_specification import FlagSpecification, flag
Expand Down
20 changes: 18 additions & 2 deletions pyclasp/option_argument.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,7 @@ def _set_value(self, value, from_ctor=False):

given_value = arg_spec.default_value

if given_value:
if given_value is not None:


if arg_spec.value_type:
Expand DownExpand Up@@ -148,7 +148,23 @@ def _set_value(self, value, from_ctor=False):
pass
else:

raise MissingValueException("the '%s' option does not have a value to be interpreted as an integer" % (self.name))
if arg_spec.value_type == bool:

type_name = "boolean"
elif arg_spec.value_type == float:

type_name = "a number"
elif arg_spec.value_type == int:

type_name = "an integer"
elif _SUPPORT_long and arg_spec.value_type == long:

type_name = "a long integer"
else:

type_name = "a value"

raise MissingValueException("the '%s' option does not have a value to be interpreted as %s" % (self.name, type_name))


self.given_value = given_value
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,7 @@

name="pyclasp",
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, !=3.7.*',
version='0.8.11',
version='0.8.12',

author="Matt Wilson",
author_email="matthew@synesis.com.au",
Expand Down
91 changes: 90 additions & 1 deletion tests/test_typed_values.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -303,10 +303,44 @@ def test_empty_option_value_of_type_int(self):

argv = ( "myprog", "--length=" )

with self.assertRaises(clasp.MissingValueException):
with self.assertRaises(clasp.MissingValueException) as ctx:

clasp.parse(argv, specifications)

self.assertEqual("the '--length' option does not have a value to be interpreted as an integer", str(ctx.exception))


def test_empty_option_value_of_type_float(self):

specifications = (

clasp.option('--length', alias='-l', value_type=float),
)

argv = ( 'myprog', '--length=' )

with self.assertRaises(clasp.MissingValueException) as ctx:

clasp.parse(argv, specifications)

self.assertEqual("the '--length' option does not have a value to be interpreted as a number", str(ctx.exception))


def test_empty_option_value_of_type_bool(self):

specifications = (

clasp.option('--length', alias='-l', value_type=bool),
)

argv = ( 'myprog', '--length=' )

with self.assertRaises(clasp.MissingValueException) as ctx:

clasp.parse(argv, specifications)

self.assertEqual("the '--length' option does not have a value to be interpreted as boolean", str(ctx.exception))


def test_empty_option_value_of_type_int_2(self):

Expand DownExpand Up@@ -442,6 +476,61 @@ def test_flags_of_flags_and_options_combined(self):
self.assertEqual(0, len(args.values))


def test_reproduce_falsy_default_issue(self):

specifications = (
clasp.option(
"--depth",
alias="-d",
default=0,
value_type=int,
),
clasp.option(
"--exchange",
alias="-e",
required=True,
value_type=str,
),
)

argv = ('liquidity-assessor', '-e', 'bybit', '-d', '10')
args = clasp.parse(argv, specifications)

self.assertEqual(2, len(args.options))

depth_option = next(opt for opt in args.options if opt.name == '--depth')
self.assertEqual(10, depth_option.value)

exchange_option = next(opt for opt in args.options if opt.name == '--exchange')
self.assertEqual('bybit', exchange_option.value)


def test_reproduce_falsy_default_issue_with_default_used(self):

specifications = (
clasp.option(
"--depth",
alias="-d",
default=0,
value_type=int,
),
clasp.option(
"--exchange",
alias="-e",
required=True,
value_type=str,
),
)

argv = ('liquidity-assessor', '-e', 'bybit')
args = clasp.parse(argv, specifications)

# In CLASP, options with defaults are not automatically added to args.options unless specified on the CLI or if we lookup/access them?
# Wait, let's verify if they are added or not.
self.assertEqual(1, len(args.options))
exchange_option = args.options[0]
self.assertEqual('bybit', exchange_option.value)


if '__main__' == __name__:

Expand Down
Loading