python-dotenv
Advanced tools
+20
-3
@@ -8,2 +8,19 @@ # Changelog | ||
| ## [0.21.1] - 2022-09-03 | ||
| ### Added | ||
| * Use Python 3.11 non-beta in CI (#438 by @bbc2) | ||
| * Modernize variables code (#434 by @Nougat-Waffle) | ||
| * Modernize main.py and parser.py code (#435 by @Nougat-Waffle) | ||
| * Improve conciseness of cli.py and __init__.py (#439 by @Nougat-Waffle) | ||
| * Improve error message for `get` and `list` commands when env file can't be opened (#441 by @bbc2) | ||
| * Updated Licence to align with BSD OSI template (#433 by @lsmith77) | ||
| ### Fixed | ||
| * Fix Out-of-scope error when "dest" variable is undefined (#413 by @theGOTOguy) | ||
| * Fix IPython test warning about deprecated `magic` (#440 by @bbc2) | ||
| * Fix type hint for dotenv_path var, add StrPath alias (#432 by @eaf) | ||
| ## [0.21.0] - 2022-09-03 | ||
@@ -20,5 +37,5 @@ | ||
| * Improve documentation for variables without a value (#390 by @bbc2) | ||
| * Add `parse_it` to Related Projects by (#410 by @naorlivne) | ||
| * Update README.md by (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs by (#398 by @bbc2) | ||
| * Add `parse_it` to Related Projects (#410 by @naorlivne) | ||
| * Update README.md (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs (#398 by @bbc2) | ||
@@ -25,0 +42,0 @@ ## [0.20.0] - 2022-03-24 |
+20
-3
@@ -8,2 +8,19 @@ # Changelog | ||
| ## [0.21.1] - 2022-09-03 | ||
| ### Added | ||
| * Use Python 3.11 non-beta in CI (#438 by @bbc2) | ||
| * Modernize variables code (#434 by @Nougat-Waffle) | ||
| * Modernize main.py and parser.py code (#435 by @Nougat-Waffle) | ||
| * Improve conciseness of cli.py and __init__.py (#439 by @Nougat-Waffle) | ||
| * Improve error message for `get` and `list` commands when env file can't be opened (#441 by @bbc2) | ||
| * Updated Licence to align with BSD OSI template (#433 by @lsmith77) | ||
| ### Fixed | ||
| * Fix Out-of-scope error when "dest" variable is undefined (#413 by @theGOTOguy) | ||
| * Fix IPython test warning about deprecated `magic` (#440 by @bbc2) | ||
| * Fix type hint for dotenv_path var, add StrPath alias (#432 by @eaf) | ||
| ## [0.21.0] - 2022-09-03 | ||
@@ -20,5 +37,5 @@ | ||
| * Improve documentation for variables without a value (#390 by @bbc2) | ||
| * Add `parse_it` to Related Projects by (#410 by @naorlivne) | ||
| * Update README.md by (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs by (#398 by @bbc2) | ||
| * Add `parse_it` to Related Projects (#410 by @naorlivne) | ||
| * Update README.md (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs (#398 by @bbc2) | ||
@@ -25,0 +42,0 @@ ## [0.20.0] - 2022-03-24 |
+1
-63
@@ -1,6 +0,3 @@ | ||
| python-dotenv | ||
| Copyright (c) 2014, Saurabh Kumar | ||
| Copyright (c) 2014, Saurabh Kumar (python-dotenv), 2013, Ted Tieken (django-dotenv-rw), 2013, Jacob Kaplan-Moss (django-dotenv) | ||
| All rights reserved. | ||
| Redistribution and use in source and binary forms, with or without modification, | ||
@@ -14,32 +11,2 @@ are permitted provided that the following conditions are met: | ||
| and/or other materials provided with the distribution. | ||
| * Neither the name of python-dotenv nor the names of its contributors | ||
| may be used to endorse or promote products derived from this software | ||
| without specific prior written permission. | ||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| django-dotenv-rw | ||
| Copyright (c) 2013, Ted Tieken | ||
| All rights reserved. | ||
| Redistribution and use in source and binary forms, with or without modification, | ||
| are permitted provided that the following conditions are met: | ||
| * Redistributions of source code must retain the above copyright notice, | ||
| this list of conditions and the following disclaimer. | ||
| * Redistributions in binary form must reproduce the above copyright notice, | ||
| this list of conditions and the following disclaimer in the documentation | ||
| and/or other materials provided with the distribution. | ||
| * Neither the name of django-dotenv nor the names of its contributors | ||
@@ -60,30 +27,1 @@ may be used to endorse or promote products derived from this software | ||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| Original django-dotenv | ||
| Copyright (c) 2013, Jacob Kaplan-Moss | ||
| All rights reserved. | ||
| Redistribution and use in source and binary forms, with or without modification, | ||
| are permitted provided that the following conditions are met: | ||
| * Redistributions of source code must retain the above copyright notice, | ||
| this list of conditions and the following disclaimer. | ||
| * Redistributions in binary form must reproduce the above copyright notice, | ||
| this list of conditions and the following disclaimer in the documentation | ||
| and/or other materials provided with the distribution. | ||
| * Neither the name of django-dotenv nor the names of its contributors | ||
| may be used to endorse or promote products derived from this software | ||
| without specific prior written permission. | ||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+21
-4
| Metadata-Version: 2.1 | ||
| Name: python-dotenv | ||
| Version: 0.21.0 | ||
| Version: 0.21.1 | ||
| Summary: Read key-value pairs from a .env file and set them as environment variables | ||
@@ -285,2 +285,19 @@ Home-page: https://github.com/theskumar/python-dotenv | ||
| ## [0.21.1] - 2022-09-03 | ||
| ### Added | ||
| * Use Python 3.11 non-beta in CI (#438 by @bbc2) | ||
| * Modernize variables code (#434 by @Nougat-Waffle) | ||
| * Modernize main.py and parser.py code (#435 by @Nougat-Waffle) | ||
| * Improve conciseness of cli.py and __init__.py (#439 by @Nougat-Waffle) | ||
| * Improve error message for `get` and `list` commands when env file can't be opened (#441 by @bbc2) | ||
| * Updated Licence to align with BSD OSI template (#433 by @lsmith77) | ||
| ### Fixed | ||
| * Fix Out-of-scope error when "dest" variable is undefined (#413 by @theGOTOguy) | ||
| * Fix IPython test warning about deprecated `magic` (#440 by @bbc2) | ||
| * Fix type hint for dotenv_path var, add StrPath alias (#432 by @eaf) | ||
| ## [0.21.0] - 2022-09-03 | ||
@@ -297,5 +314,5 @@ | ||
| * Improve documentation for variables without a value (#390 by @bbc2) | ||
| * Add `parse_it` to Related Projects by (#410 by @naorlivne) | ||
| * Update README.md by (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs by (#398 by @bbc2) | ||
| * Add `parse_it` to Related Projects (#410 by @naorlivne) | ||
| * Update README.md (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs (#398 by @bbc2) | ||
@@ -302,0 +319,0 @@ ## [0.20.0] - 2022-03-24 |
+1
-1
| [bumpversion] | ||
| current_version = 0.21.0 | ||
| current_version = 0.21.1 | ||
| commit = True | ||
@@ -4,0 +4,0 @@ tag = True |
@@ -26,5 +26,5 @@ from typing import Any, Optional | ||
| if quote: | ||
| command.append('-q %s' % quote) | ||
| command.append(f'-q {quote}') | ||
| if path: | ||
| command.append('-f %s' % path) | ||
| command.append(f'-f {path}') | ||
| if action: | ||
@@ -36,3 +36,3 @@ command.append(action) | ||
| if ' ' in value: | ||
| command.append('"%s"' % value) | ||
| command.append(f'"{value}"') | ||
| else: | ||
@@ -39,0 +39,0 @@ command.append(value) |
+41
-30
@@ -5,4 +5,5 @@ import json | ||
| import sys | ||
| from contextlib import contextmanager | ||
| from subprocess import Popen | ||
| from typing import Any, Dict, List | ||
| from typing import Any, Dict, IO, Iterator, List | ||
@@ -16,3 +17,3 @@ try: | ||
| from .main import dotenv_values, get_key, set_key, unset_key | ||
| from .main import dotenv_values, set_key, unset_key | ||
| from .version import __version__ | ||
@@ -34,9 +35,22 @@ | ||
| def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: | ||
| '''This script is used to set, get or unset values from a .env file.''' | ||
| ctx.obj = {} | ||
| ctx.obj['QUOTE'] = quote | ||
| ctx.obj['EXPORT'] = export | ||
| ctx.obj['FILE'] = file | ||
| """This script is used to set, get or unset values from a .env file.""" | ||
| ctx.obj = {'QUOTE': quote, 'EXPORT': export, 'FILE': file} | ||
| @contextmanager | ||
| def stream_file(path: os.PathLike) -> Iterator[IO[str]]: | ||
| """ | ||
| Open a file and yield the corresponding (decoded) stream. | ||
| Exits with error code 2 if the file cannot be opened. | ||
| """ | ||
| try: | ||
| with open(path) as stream: | ||
| yield stream | ||
| except OSError as exc: | ||
| print(f"Error opening env file: {exc}", file=sys.stderr) | ||
| exit(2) | ||
| @cli.command() | ||
@@ -49,20 +63,18 @@ @click.pass_context | ||
| def list(ctx: click.Context, format: bool) -> None: | ||
| '''Display all the stored key/value.''' | ||
| """Display all the stored key/value.""" | ||
| file = ctx.obj['FILE'] | ||
| if not os.path.isfile(file): | ||
| raise click.BadParameter( | ||
| 'Path "%s" does not exist.' % (file), | ||
| ctx=ctx | ||
| ) | ||
| dotenv_as_dict = dotenv_values(file) | ||
| with stream_file(file) as stream: | ||
| values = dotenv_values(stream=stream) | ||
| if format == 'json': | ||
| click.echo(json.dumps(dotenv_as_dict, indent=2, sort_keys=True)) | ||
| click.echo(json.dumps(values, indent=2, sort_keys=True)) | ||
| else: | ||
| prefix = 'export ' if format == 'export' else '' | ||
| for k in sorted(dotenv_as_dict): | ||
| v = dotenv_as_dict[k] | ||
| for k in sorted(values): | ||
| v = values[k] | ||
| if v is not None: | ||
| if format in ('export', 'shell'): | ||
| v = shlex.quote(v) | ||
| click.echo('%s%s=%s' % (prefix, k, v)) | ||
| click.echo(f'{prefix}{k}={v}') | ||
@@ -75,3 +87,3 @@ | ||
| def set(ctx: click.Context, key: Any, value: Any) -> None: | ||
| '''Store the given key/value.''' | ||
| """Store the given key/value.""" | ||
| file = ctx.obj['FILE'] | ||
@@ -82,3 +94,3 @@ quote = ctx.obj['QUOTE'] | ||
| if success: | ||
| click.echo('%s=%s' % (key, value)) | ||
| click.echo(f'{key}={value}') | ||
| else: | ||
@@ -92,10 +104,9 @@ exit(1) | ||
| def get(ctx: click.Context, key: Any) -> None: | ||
| '''Retrieve the value for the given key.''' | ||
| """Retrieve the value for the given key.""" | ||
| file = ctx.obj['FILE'] | ||
| if not os.path.isfile(file): | ||
| raise click.BadParameter( | ||
| 'Path "%s" does not exist.' % (file), | ||
| ctx=ctx | ||
| ) | ||
| stored_value = get_key(file, key) | ||
| with stream_file(file) as stream: | ||
| values = dotenv_values(stream=stream) | ||
| stored_value = values.get(key) | ||
| if stored_value: | ||
@@ -111,3 +122,3 @@ click.echo(stored_value) | ||
| def unset(ctx: click.Context, key: Any) -> None: | ||
| '''Removes the given key.''' | ||
| """Removes the given key.""" | ||
| file = ctx.obj['FILE'] | ||
@@ -117,3 +128,3 @@ quote = ctx.obj['QUOTE'] | ||
| if success: | ||
| click.echo("Successfully removed %s" % key) | ||
| click.echo(f"Successfully removed {key}") | ||
| else: | ||
@@ -136,3 +147,3 @@ exit(1) | ||
| raise click.BadParameter( | ||
| 'Invalid value for \'-f\' "%s" does not exist.' % (file), | ||
| f'Invalid value for \'-f\' "{file}" does not exist.', | ||
| ctx=ctx | ||
@@ -139,0 +150,0 @@ ) |
+37
-33
@@ -15,2 +15,8 @@ import io | ||
| # A type alias for a string path to be used for the paths in this file. | ||
| # These paths may flow to `open()` and `shutil.move()`; `shutil.move()` | ||
| # only accepts string paths, not byte paths or file descriptors. See | ||
| # https://github.com/python/typeshed/pull/6832. | ||
| StrPath = Union[str, 'os.PathLike[str]'] | ||
| logger = logging.getLogger(__name__) | ||
@@ -29,19 +35,19 @@ | ||
| class DotEnv(): | ||
| class DotEnv: | ||
| def __init__( | ||
| self, | ||
| dotenv_path: Optional[Union[str, os.PathLike]], | ||
| dotenv_path: Optional[StrPath], | ||
| stream: Optional[IO[str]] = None, | ||
| verbose: bool = False, | ||
| encoding: Union[None, str] = None, | ||
| encoding: Optional[str] = None, | ||
| interpolate: bool = True, | ||
| override: bool = True, | ||
| ) -> None: | ||
| self.dotenv_path = dotenv_path # type: Optional[Union[str, os.PathLike]] | ||
| self.stream = stream # type: Optional[IO[str]] | ||
| self._dict = None # type: Optional[Dict[str, Optional[str]]] | ||
| self.verbose = verbose # type: bool | ||
| self.encoding = encoding # type: Union[None, str] | ||
| self.interpolate = interpolate # type: bool | ||
| self.override = override # type: bool | ||
| self.dotenv_path: Optional[StrPath] = dotenv_path | ||
| self.stream: Optional[IO[str]] = stream | ||
| self._dict: Optional[Dict[str, Optional[str]]] = None | ||
| self.verbose: bool = verbose | ||
| self.encoding: Optional[str] = encoding | ||
| self.interpolate: bool = interpolate | ||
| self.override: bool = override | ||
@@ -113,3 +119,3 @@ @contextmanager | ||
| def get_key( | ||
| dotenv_path: Union[str, os.PathLike], | ||
| dotenv_path: StrPath, | ||
| key_to_get: str, | ||
@@ -128,22 +134,20 @@ encoding: Optional[str] = "utf-8", | ||
| def rewrite( | ||
| path: Union[str, os.PathLike], | ||
| path: StrPath, | ||
| encoding: Optional[str], | ||
| ) -> Iterator[Tuple[IO[str], IO[str]]]: | ||
| try: | ||
| if not os.path.isfile(path): | ||
| with open(path, "w+", encoding=encoding) as source: | ||
| source.write("") | ||
| with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding=encoding) as dest: | ||
| if not os.path.isfile(path): | ||
| with open(path, mode="w", encoding=encoding) as source: | ||
| source.write("") | ||
| with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest: | ||
| try: | ||
| with open(path, encoding=encoding) as source: | ||
| yield (source, dest) # type: ignore | ||
| except BaseException: | ||
| if os.path.isfile(dest.name): | ||
| yield (source, dest) | ||
| except BaseException: | ||
| os.unlink(dest.name) | ||
| raise | ||
| else: | ||
| shutil.move(dest.name, path) | ||
| raise | ||
| shutil.move(dest.name, path) | ||
| def set_key( | ||
| dotenv_path: Union[str, os.PathLike], | ||
| dotenv_path: StrPath, | ||
| key_to_set: str, | ||
@@ -162,3 +166,3 @@ value_to_set: str, | ||
| if quote_mode not in ("always", "auto", "never"): | ||
| raise ValueError("Unknown quote_mode: {}".format(quote_mode)) | ||
| raise ValueError(f"Unknown quote_mode: {quote_mode}") | ||
@@ -175,5 +179,5 @@ quote = ( | ||
| if export: | ||
| line_out = 'export {}={}\n'.format(key_to_set, value_out) | ||
| line_out = f'export {key_to_set}={value_out}\n' | ||
| else: | ||
| line_out = "{}={}\n".format(key_to_set, value_out) | ||
| line_out = f"{key_to_set}={value_out}\n" | ||
@@ -199,3 +203,3 @@ with rewrite(dotenv_path, encoding=encoding) as (source, dest): | ||
| def unset_key( | ||
| dotenv_path: Union[str, os.PathLike], | ||
| dotenv_path: StrPath, | ||
| key_to_unset: str, | ||
@@ -234,3 +238,3 @@ quote_mode: str = "always", | ||
| ) -> Mapping[str, Optional[str]]: | ||
| new_values = {} # type: Dict[str, Optional[str]] | ||
| new_values: Dict[str, Optional[str]] = {} | ||
@@ -242,3 +246,3 @@ for (name, value) in values: | ||
| atoms = parse_variables(value) | ||
| env = {} # type: Dict[str, Optional[str]] | ||
| env: Dict[str, Optional[str]] = {} | ||
| if override: | ||
@@ -317,3 +321,3 @@ env.update(os.environ) # type: ignore | ||
| def load_dotenv( | ||
| dotenv_path: Union[str, os.PathLike, None] = None, | ||
| dotenv_path: Optional[StrPath] = None, | ||
| stream: Optional[IO[str]] = None, | ||
@@ -336,3 +340,3 @@ verbose: bool = False, | ||
| Returns: | ||
| Bool: True if atleast one environment variable is set elese False | ||
| Bool: True if at least one environment variable is set else False | ||
@@ -357,3 +361,3 @@ If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the | ||
| def dotenv_values( | ||
| dotenv_path: Union[str, os.PathLike, None] = None, | ||
| dotenv_path: Optional[StrPath] = None, | ||
| stream: Optional[IO[str]] = None, | ||
@@ -360,0 +364,0 @@ verbose: bool = False, |
+10
-17
@@ -28,21 +28,14 @@ import codecs | ||
| Original = NamedTuple( | ||
| "Original", | ||
| [ | ||
| ("string", str), | ||
| ("line", int), | ||
| ], | ||
| ) | ||
| class Original(NamedTuple): | ||
| string: str | ||
| line: int | ||
| Binding = NamedTuple( | ||
| "Binding", | ||
| [ | ||
| ("key", Optional[str]), | ||
| ("value", Optional[str]), | ||
| ("original", Original), | ||
| ("error", bool), | ||
| ], | ||
| ) | ||
| class Binding(NamedTuple): | ||
| key: Optional[str] | ||
| value: Optional[str] | ||
| original: Original | ||
| error: bool | ||
| class Position: | ||
@@ -159,3 +152,3 @@ def __init__(self, chars: int, line: int) -> None: | ||
| reader.read_regex(_equal_sign) | ||
| value = parse_value(reader) # type: Optional[str] | ||
| value: Optional[str] = parse_value(reader) | ||
| else: | ||
@@ -162,0 +155,0 @@ value = None |
+10
-12
| import re | ||
| from abc import ABCMeta | ||
| from abc import ABCMeta, abstractmethod | ||
| from typing import Iterator, Mapping, Optional, Pattern | ||
| _posix_variable = re.compile( | ||
| _posix_variable: Pattern[str] = re.compile( | ||
| r""" | ||
@@ -15,8 +15,6 @@ \$\{ | ||
| re.VERBOSE, | ||
| ) # type: Pattern[str] | ||
| ) | ||
| class Atom(): | ||
| __metaclass__ = ABCMeta | ||
| class Atom(metaclass=ABCMeta): | ||
| def __ne__(self, other: object) -> bool: | ||
@@ -28,4 +26,4 @@ result = self.__eq__(other) | ||
| def resolve(self, env: Mapping[str, Optional[str]]) -> str: | ||
| raise NotImplementedError | ||
| @abstractmethod | ||
| def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... | ||
@@ -38,3 +36,3 @@ | ||
| def __repr__(self) -> str: | ||
| return "Literal(value={})".format(self.value) | ||
| return f"Literal(value={self.value})" | ||
@@ -59,3 +57,3 @@ def __eq__(self, other: object) -> bool: | ||
| def __repr__(self) -> str: | ||
| return "Variable(name={}, default={})".format(self.name, self.default) | ||
| return f"Variable(name={self.name}, default={self.default})" | ||
@@ -81,4 +79,4 @@ def __eq__(self, other: object) -> bool: | ||
| (start, end) = match.span() | ||
| name = match.groupdict()["name"] | ||
| default = match.groupdict()["default"] | ||
| name = match["name"] | ||
| default = match["default"] | ||
@@ -85,0 +83,0 @@ if start > cursor: |
@@ -1,1 +0,1 @@ | ||
| __version__ = "0.21.0" | ||
| __version__ = "0.21.1" |
| Metadata-Version: 2.1 | ||
| Name: python-dotenv | ||
| Version: 0.21.0 | ||
| Version: 0.21.1 | ||
| Summary: Read key-value pairs from a .env file and set them as environment variables | ||
@@ -285,2 +285,19 @@ Home-page: https://github.com/theskumar/python-dotenv | ||
| ## [0.21.1] - 2022-09-03 | ||
| ### Added | ||
| * Use Python 3.11 non-beta in CI (#438 by @bbc2) | ||
| * Modernize variables code (#434 by @Nougat-Waffle) | ||
| * Modernize main.py and parser.py code (#435 by @Nougat-Waffle) | ||
| * Improve conciseness of cli.py and __init__.py (#439 by @Nougat-Waffle) | ||
| * Improve error message for `get` and `list` commands when env file can't be opened (#441 by @bbc2) | ||
| * Updated Licence to align with BSD OSI template (#433 by @lsmith77) | ||
| ### Fixed | ||
| * Fix Out-of-scope error when "dest" variable is undefined (#413 by @theGOTOguy) | ||
| * Fix IPython test warning about deprecated `magic` (#440 by @bbc2) | ||
| * Fix type hint for dotenv_path var, add StrPath alias (#432 by @eaf) | ||
| ## [0.21.0] - 2022-09-03 | ||
@@ -297,5 +314,5 @@ | ||
| * Improve documentation for variables without a value (#390 by @bbc2) | ||
| * Add `parse_it` to Related Projects by (#410 by @naorlivne) | ||
| * Update README.md by (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs by (#398 by @bbc2) | ||
| * Add `parse_it` to Related Projects (#410 by @naorlivne) | ||
| * Update README.md (#415 by @harveer07) | ||
| * Improve documentation with direct use of MkDocs (#398 by @bbc2) | ||
@@ -302,0 +319,0 @@ ## [0.20.0] - 2022-03-24 |
+17
-3
@@ -43,5 +43,12 @@ import os | ||
| assert result.exit_code == 2, result.output | ||
| assert "does not exist" in result.output | ||
| assert "Error opening env file" in result.output | ||
| def test_list_not_a_file(cli): | ||
| result = cli.invoke(dotenv_cli, ['--file', '.', 'list']) | ||
| assert result.exit_code == 2, result.output | ||
| assert "Error opening env file" in result.output | ||
| def test_list_no_file(cli): | ||
@@ -68,9 +75,16 @@ result = cli.invoke(dotenv.cli.list, []) | ||
| def test_get_no_file(cli): | ||
| def test_get_non_existent_file(cli): | ||
| result = cli.invoke(dotenv_cli, ['--file', 'nx_file', 'get', 'a']) | ||
| assert result.exit_code == 2 | ||
| assert "does not exist" in result.output | ||
| assert "Error opening env file" in result.output | ||
| def test_get_not_a_file(cli): | ||
| result = cli.invoke(dotenv_cli, ['--file', '.', 'get', 'a']) | ||
| assert result.exit_code == 2 | ||
| assert "Error opening env file" in result.output | ||
| def test_unset_existing_value(cli, dotenv_file): | ||
@@ -77,0 +91,0 @@ with open(dotenv_file, "w") as f: |
@@ -20,4 +20,4 @@ import os | ||
| ipshell = InteractiveShellEmbed() | ||
| ipshell.magic("load_ext dotenv") | ||
| ipshell.magic("dotenv") | ||
| ipshell.run_line_magic("load_ext", "dotenv") | ||
| ipshell.run_line_magic("dotenv", "") | ||
@@ -37,4 +37,4 @@ assert os.environ == {"a": "c"} | ||
| ipshell = InteractiveShellEmbed() | ||
| ipshell.magic("load_ext dotenv") | ||
| ipshell.magic("dotenv -o") | ||
| ipshell.run_line_magic("load_ext", "dotenv") | ||
| ipshell.run_line_magic("dotenv", "-o") | ||
@@ -53,5 +53,5 @@ assert os.environ == {"a": "b"} | ||
| ipshell = InteractiveShellEmbed() | ||
| ipshell.magic("load_ext dotenv") | ||
| ipshell.magic("dotenv") | ||
| ipshell.run_line_magic("load_ext", "dotenv") | ||
| ipshell.run_line_magic("dotenv", "") | ||
| assert os.environ == {"a": "b"} |
@@ -181,2 +181,9 @@ import io | ||
| def test_set_key_unauthorized_file(dotenv_file): | ||
| os.chmod(dotenv_file, 0o000) | ||
| with pytest.raises(PermissionError): | ||
| dotenv.set_key(dotenv_file, "a", "x") | ||
| def test_unset_non_existent_file(tmp_path): | ||
@@ -183,0 +190,0 @@ nx_file = str(tmp_path / "nx") |
+13
-11
| [tox] | ||
| envlist = lint,py{35,36,37,38,39,310,311},pypy3,manifest,coverage-report | ||
| envlist = lint,py{37,38,39,310,311},pypy3,manifest,coverage-report | ||
| [gh-actions] | ||
| python = | ||
| 3.7: py37, coverage-report | ||
| 3.8: py38, coverage-report | ||
| 3.9: py39, coverage-report | ||
| 3.10: py310, lint, manifest, coverage-report | ||
| 3.11: py311, coverage-report | ||
| pypy-3.9: pypy3, coverage-report | ||
| 3.7: py37 | ||
| 3.8: py38 | ||
| 3.9: py39 | ||
| 3.10: py310 | ||
| 3.11: py311, lint, manifest | ||
| pypy-3.9: pypy3 | ||
@@ -16,7 +16,10 @@ [testenv] | ||
| pytest | ||
| coverage | ||
| pytest-cov | ||
| sh | ||
| click | ||
| py{37,38,39,310,311,py3}: ipython | ||
| commands = coverage run --parallel -m pytest {posargs} | ||
| py{37,38,39,310,311,pypy3}: ipython | ||
| commands = pytest --cov --cov-report=term-missing --cov-config setup.cfg {posargs} | ||
| depends = | ||
| py{37,38,39,310,311},pypy3: coverage-clean | ||
| coverage-report: py{35,36,37,38,39,310,311},pypy3 | ||
@@ -50,3 +53,2 @@ [testenv:lint] | ||
| commands = | ||
| coverage combine | ||
| coverage report |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
148994
0.23%1516
0.6%