Repository: amoffat/sh (python)

Issue:
Some way to easily handle boolean options
I've been writing some scripts lately that make heavy use of including/excluding options based on some boolean flag. It's clunky:

```python
if dry_run:
    sh.rsync("-n", ...)
else:
    sh.rsync(...)
```
It would be nicer if there was something, maybe `sh.Cond` that takes an object that evaluates to truthy, and a flag to be set if that evaluation is `True`.  So:

```python
sh.rsync(sh.Cond(dry_run, "-n"), ...)
```

I'm not sure if it should be a class (`Cond`) or a function (`cond`), or something named different altogether, but I would want to minimize its chances of colliding its name with other binaries on the system. Thoughts? @ecederstrand 

Pull request:
None should not render an arg. closes #522
Pretty simple. Before, a `None` argument passed to a command was being passed in as a string. Now, it omits the argument altogether.

Patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 6ad7089..0000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-# These are supported funding model platforms
-
-github: [amoffat]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/sh.py b/sh.py
index 57d4675..2335691 100644
--- a/sh.py
+++ b/sh.py
@@ -1581,6 +1581,10 @@ def compile_args(args, kwargs, sep, prefix):
                 processed_args.append(encode(sub_arg))
         elif isinstance(arg, dict):
             processed_args += aggregate_keywords(arg, sep, prefix, raw=True)
+
+        # see https://github.com/amoffat/sh/issues/522
+        elif arg is None or arg is False:
+            pass
         else:
             processed_args.append(encode(arg))
 


Test patch:
diff --git a/test.py b/test.py
index 5dd1f14..c42df9d 100644
--- a/test.py
+++ b/test.py
@@ -383,6 +383,21 @@ exit(3)
         py = create_tmp_test("exit(0)")
         python(py.name, _ok_code=None)
 
+
+    def test_none_arg(self):
+        py = create_tmp_test("""
+import sys
+print(sys.argv[1:])
+""")
+        maybe_arg = "some"
+        out = python(py.name, maybe_arg).strip()
+        self.assertEqual(out, "['some']")
+
+        maybe_arg = None
+        out = python(py.name, maybe_arg).strip()
+        self.assertEqual(out, "[]")
+
+
     def test_quote_escaping(self):
         py = create_tmp_test("""
 from optparse import OptionParser
@@ -821,6 +836,17 @@ print(options.long_option)
         self.assertTrue(python(py.name).strip() == "False")
 
 
+    def test_false_bool_ignore(self):
+        py = create_tmp_test("""
+import sys
+print(sys.argv[1:])
+""")
+        test = True
+        self.assertEqual(python(py.name, test and "-n").strip(), "['-n']")
+        test = False
+        self.assertEqual(python(py.name, test and "-n").strip(), "[]")
+
+
     def test_composition(self):
         from sh import ls, wc
         c1 = int(wc(ls("-A1"), l=True))