Skip to content

Commit

Permalink
Merge pull request #37 from teald/18-allow-positional-only-arguments-…
Browse files Browse the repository at this point in the history
…in-functions

18 allow positional only arguments in functions
  • Loading branch information
teald authored Nov 29, 2022
2 parents 266db82 + 0033ca8 commit 256d349
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
18 changes: 11 additions & 7 deletions porchlight/door.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class BaseDoor:
Dictionary of all arguments taken as input when the `BaseDoor` object
is called.
positional_only : :py:obj:`list` of :py:obj:`str`
List of positional-only arguments accepted by the function.
keyword_args : :py:obj:`dict`, :py:obj:`str`: :class:`~typing.Any`
Keyword arguments accepted by the `BaseDoor` as input when called. This
includes all arguments that are not positional-only. Positional
Expand Down Expand Up @@ -146,6 +149,7 @@ def _inspect_base_callable(self):
self.name = function.__name__
self.__name__ = function.__name__
self.arguments = {}
self.positional_only = []
self.keyword_args = {}
self.keyword_only_args = {}

Expand All @@ -164,19 +168,19 @@ def _inspect_base_callable(self):

self.return_types = None

# Use function signature to introspect properties about the parameters.
for name, param in inspect.signature(function).parameters.items():
self.arguments[name] = param.annotation

# Check for positional-only arguments first, then proceed to other
# argument types.
if param.kind == inspect.Parameter.POSITIONAL_ONLY:
msg = (
f"porchlight does not support positional-only "
f"arguments, which were found in {self.name}."
)

logger.error(msg)
raise NotImplementedError(msg)
# Positional-only arguments will not support default values for
# the function. That said, this is effectively overriden by
# Neighborhood objects, since they store the parameter's value
# and pass it regardless of whether the argument is
# positional-only or not.
self.positional_only.append(name)

elif param.default != inspect._empty:
self.keyword_args[name] = Param(name, param.default)
Expand Down
27 changes: 18 additions & 9 deletions porchlight/tests/test_basedoor.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,24 @@ def bigfxn(x, y, *, z=5):

self.assertEqual(new_door.keyword_only_args, {"z": Param("z", 5)})

# For now, there should *not* be any functionality for required
# positional arguments. That will come later, and this test will need
# to be updated.
def bad_fxn(x1, y1, /, x3, *, z7):
c = "blah"
return c

with self.assertRaises(NotImplementedError):
BaseDoor(bad_fxn)
# Positional-only arguments.
def test1(
pos1, pos2, /, kwpos, kwposdef="default", *, kwonly="def4ult"
):
pass

new_door = BaseDoor(test1)

expected_arguments = {
"pos1": Empty(),
"pos2": Empty(),
"kwpos": Empty(),
"kwposdef": Empty(),
"kwonly": Empty,
}

self.assertEqual(new_door.arguments, expected_arguments)
self.assertEqual(new_door.positional_only, ["pos1", "pos2"])

def test__returned_def_to_door(self):
def my_func_gen():
Expand Down

0 comments on commit 256d349

Please sign in to comment.