Repository: joke2k/django-environ
Pull request #323 (2021-09-05 12:01:02)

Use default option in Env.bytes()
Closes https://github.com/joke2k/django-environ/pull/206


Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b221941..3aafe60 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -15,11 +15,14 @@ Added
     (`#297 <https://github.com/joke2k/django-environ/pull/297>`_)
   - Added Elasticsearch7 to search scheme
     (`#314 <https://github.com/joke2k/django-environ/pull/314>`_)
+  - Provided ability to use ``bytes`` or ``str`` as a default value for ``Env.bytes()``
 
 
 Fixed
 +++++
   - Fixed links in the documentation
+  - Use default option in ``Env.bytes()``
+    (`#206 <https://github.com/joke2k/django-environ/pull/206>`_)
 
 Changed
 +++++++
@@ -34,6 +37,7 @@ Added
   - Django 3.1 and 3.2 are now supported
   - Added missed classifiers to ``setup.py``
   - Accept Python 3.6 path-like objects for ``read_env``
+    (`#106 <https://github.com/joke2k/django-environ/issues/106>`_, `#286 <https://github.com/joke2k/django-environ/issues/286>`_)
 
 Fixed
 +++++
@@ -41,6 +45,7 @@ Fixed
   - Fixed typos in the documentation
   - Added missed files to the package contents
   - Fixed ``db_url_config`` to work the same for all postgres-like schemes
+    (`#264 <https://github.com/joke2k/django-environ/issues/264>`_, `#268 <https://github.com/joke2k/django-environ/issues/268>`_)
 
 Changed
 +++++++
diff --git a/environ/environ.py b/environ/environ.py
index 2dad620..b91d3ff 100644
--- a/environ/environ.py
+++ b/environ/environ.py
@@ -193,7 +193,10 @@ class Env:
         """
         :rtype: bytes
         """
-        return self.get_value(var, cast=str).encode(encoding)
+        value = self.get_value(var, cast=str, default=default)
+        if hasattr(value, 'encode'):
+            return value.encode(encoding)
+        return value
 
     def bool(self, var, default=NOTSET):
         """
@@ -360,8 +363,9 @@ class Env:
             value = default
 
         # Resolve any proxied values
-        if hasattr(value, 'startswith') and value.startswith('$'):
-            value = value.lstrip('$')
+        prefix = b'$' if isinstance(value, bytes) else '$'
+        if hasattr(value, 'startswith') and value.startswith(prefix):
+            value = value.lstrip(prefix)
             value = self.get_value(value, cast=cast, default=default)
 
         # Smart casting


Test patch:
diff --git a/tests/test_env.py b/tests/test_env.py
index 12fe9b4..efb09fb 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -65,8 +65,16 @@ class TestEnv:
             assert self.env(var) == val
         assert self.env.str(var, multiline=multiline) == val
 
-    def test_bytes(self):
-        assert_type_and_value(bytes, b'bar', self.env.bytes('STR_VAR'))
+    @pytest.mark.parametrize(
+        'var,val,default',
+        [
+            ('STR_VAR', b'bar', Env.NOTSET),
+            ('NON_EXISTENT_BYTES_VAR', b'some-default', b'some-default'),
+            ('NON_EXISTENT_STR_VAR', b'some-default', 'some-default'),
+        ]
+    )
+    def test_bytes(self, var, val, default):
+        assert_type_and_value(bytes, val, self.env.bytes(var, default=default))
 
     def test_int(self):
         assert_type_and_value(int, 42, self.env('INT_VAR', cast=int))