summaryrefslogtreecommitdiffstats
path: root/source/api.py
diff options
context:
space:
mode:
Diffstat (limited to 'source/api.py')
-rw-r--r--source/api.py66
1 files changed, 64 insertions, 2 deletions
diff --git a/source/api.py b/source/api.py
index c16110b..38993b5 100644
--- a/source/api.py
+++ b/source/api.py
@@ -227,10 +227,56 @@ def _setter(field):
# Various Utilities
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-def listed(items, quote=""):
- """ Convert provided iterable into a nice, human readable list. """
+def listed(items, singular=None, plural=None, max=None, quote=""):
+ """
+ Convert an iterable into a nice, human readable list or description.
+
+ listed(range(1)) .................... 0
+ listed(range(2)) .................... 0 and 1
+ listed(range(3), quote='"') ......... "0", "1" and "2"
+ listed(range(4), max=3) ............. 0, 1, 2 and 1 more
+ listed(range(5), 'number', max=3) ... 0, 1, 2 and 2 more numbers
+ listed(range(6), 'category') ........ 6 categories
+ listed(7, "leaf", "leaves") ......... 7 leaves
+
+ If singular form is provided but max not set the description-only
+ mode is activated as shown in the last two examples. Also, an int
+ can be used in this case to get a simple inflection functionality.
+ """
+
+ # Convert items to list if necessary
+ if isinstance(items, int):
+ items = range(items)
+ elif not isinstance(items, list):
+ items = list(items)
+ more = " more"
+ # Description mode expected when singular provided but no maximum set
+ if singular is not None and max is None:
+ max = 0
+ more = ""
+ # Set the default plural form
+ if singular is not None and plural is None:
+ if singular.endswith("y"):
+ plural = singular[:-1] + "ies"
+ else:
+ plural = singular + "s"
+ # Convert to strings and optionally quote each item
items = ["{0}{1}{0}".format(quote, item) for item in items]
+ # Select the maximum of items and describe the rest if max provided
+ if max is not None:
+ # Special case when the list is empty (0 items)
+ if max == 0 and len(items) == 0:
+ return "0 {0}".format(plural)
+ # Cut the list if maximum exceeded
+ if len(items) > max:
+ rest = len(items[max:])
+ items = items[:max]
+ if singular is not None:
+ more += " {0}".format(singular if rest == 1 else plural)
+ items.append("{0}{1}".format(rest, more))
+
+ # For two and more items use 'and' instead of the last comma
if len(items) < 2:
return "".join(items)
else:
@@ -412,6 +458,22 @@ class Nitrate(object):
""" Fetch object data from the server. """
raise NitrateError("To be implemented by respective class")
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ # Nitrate Self Test
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ class _test(unittest.TestCase):
+ def test_listed(self):
+ """ Function listed() sanity """
+ self.assertEqual(listed(range(1)), "0")
+ self.assertEqual(listed(range(2)), "0 and 1")
+ self.assertEqual(listed(range(3), quote='"'), '"0", "1" and "2"')
+ self.assertEqual(listed(range(4), max=3), "0, 1, 2 and 1 more")
+ self.assertEqual(listed(range(5), 'number', max=3),
+ "0, 1, 2 and 2 more numbers")
+ self.assertEqual(listed(range(6), 'category'), "6 categories")
+ self.assertEqual(listed(7, "leaf", "leaves"), "7 leaves")
+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Build Class