Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: theskumar/python-dotenv
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.1
Choose a base ref
...
head repository: theskumar/python-dotenv
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.1.0
Choose a head ref
  • 16 commits
  • 14 files changed
  • 9 contributors

Commits on Apr 7, 2024

  1. Add a security policy

    This is a basic security policy, mostly to provide an email address. I
    took inspiration from the example provided by GitHub and the policy from
    the Pallets project.
    bbc2 committed Apr 7, 2024
    Copy the full SHA
    6d6070c View commit details

Commits on Apr 8, 2024

  1. Copy the full SHA
    bf20c80 View commit details
  2. ci: fix multiline string in test.yml & use fail-fast strategy (#514)

    * Fix multiline string in test.yml
    
    * strategy: fail-fast: false
    
    * Update test.yml
    cclauss authored Apr 8, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    lforst Luca Forstner
    Copy the full SHA
    8c9381e View commit details

Commits on Apr 29, 2024

  1. docs: clearify default behaviour of load_dotenv

    closes #457
    theskumar committed Apr 29, 2024
    Copy the full SHA
    08937a1 View commit details

Commits on Jul 18, 2024

  1. Enhance dotenv run: Switch to execvpe for better resource management …

    …and signal handling (#523)
    
    The current implementation of `dotenv run` CLI uses `subprocess.Popen`, which spawns a child process to execute the specified command. 
    
    ```
    p = Popen(command,
                  universal_newlines=True,
                  bufsize=0,
                  shell=False,
                  env=cmd_env)
    ```
    
    After spawning the child process, it exits with the same exit code returned by the child process.
    
    ```
    ret = run_command(commandline, dotenv_as_dict)
    exit(ret)
    ```
    
    ### We can enhance `dotenv run` usage dramatically while preserving exactly the same behaviour
    
    By switching to `os.execvpe` instead of `subprocess.Popen`, we can replace the parent dotenv process with the new process specified by the user. This results in only one active process—the program the user intended to run.
    
    **Benefits:**
    
    1. No hanging parent process
        `dotenv run` acts as a launcher, so after executing `dotenv run redis-server`, only the Redis server process remains. The dotenv process, along with its Python interpreter, is completely replaced. This prevents the dotenv process from consuming RAM and other resources, which would otherwise persist until the Redis server exits.
    
    2. Proper signal handling
        When using `subprocess.Popen`, the parent process (e.g., `dotenv`) remains responsible for handling and forwarding signals, which can lead to issues if the command doesn’t receive them directly. For instance, in Docker, if Redis was started without `exec`, it may not get important signals like `SIGTERM` when the container stops, potentially resulting in improper shutdowns or zombie processes. Using `os.execvpe` ensures that the command receives signals directly, improving reliability and making `dotenv` more suitable for production environments and improving reliability for DevOps engineers managing containerized applications.
        
    All current logic will be preserved because dotenv run does not do anything special except propagate the child process exit code.
    
    Thanks / @eekstunt
    eekstunt authored Jul 18, 2024
    Copy the full SHA
    4543837 View commit details

Commits on Jul 23, 2024

  1. ci: add py3.13 to test.yml (#527)

    * ci: add py3.13 to test.yml
    
    * Improve type hints
    
    * fix typo
    waketzheng authored Jul 23, 2024
    Copy the full SHA
    4d505f2 View commit details

Commits on Nov 1, 2024

  1. Add Python 3.13 trove classifier (#535)

    edgarrmondragon authored Nov 1, 2024
    Copy the full SHA
    533f8ac View commit details
  2. Bump the github-actions group with 2 updates (#529)

    Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-python](https://github.com/actions/setup-python).
    
    
    Updates `actions/checkout` from 2 to 4
    - [Release notes](https://github.com/actions/checkout/releases)
    - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
    - [Commits](actions/checkout@v2...v4)
    
    Updates `actions/setup-python` from 2 to 5
    - [Release notes](https://github.com/actions/setup-python/releases)
    - [Commits](actions/setup-python@v2...v5)
    
    ---
    updated-dependencies:
    - dependency-name: actions/checkout
      dependency-type: direct:production
      update-type: version-update:semver-major
      dependency-group: github-actions
    - dependency-name: actions/setup-python
      dependency-type: direct:production
      update-type: version-update:semver-major
      dependency-group: github-actions
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Nov 1, 2024
    Copy the full SHA
    2b8635b View commit details

Commits on Mar 9, 2025

  1. Add support for python 3.13 and drop 3.8 (#551)

    fixes #550
    theskumar authored Mar 9, 2025
    Copy the full SHA
    4159388 View commit details
  2. s/Python-dotenv/python-dotenv/ (#516)

    This commit uses the name `python-dotenv` instead of `Python-dotenv` in the README.md file
    chapeupreto authored Mar 9, 2025
    Copy the full SHA
    3c19c03 View commit details
  3. Some more s/Python-dotenv/python-dotenv/ (#552)

    theskumar authored Mar 9, 2025
    Copy the full SHA
    9acba4a View commit details

Commits on Mar 25, 2025

  1. Add _is_debugger so load_dotenv will work in pdb (#553)

    randomseed42 authored Mar 25, 2025
    Copy the full SHA
    8dd413e View commit details
  2. Update changelog

    theskumar committed Mar 25, 2025
    Copy the full SHA
    c89fb6d View commit details
  3. Bump version: 1.0.1 → 1.1.0

    theskumar committed Mar 25, 2025
    Copy the full SHA
    2198b69 View commit details
  4. Update changelog

    theskumar committed Mar 25, 2025
    Copy the full SHA
    36c6270 View commit details
  5. update mkdocs -> mkdocstrings config

    theskumar committed Mar 25, 2025
    Copy the full SHA
    6a02ef5 View commit details
Showing with 195 additions and 147 deletions.
  1. +18 −0 .github/SECURITY.md
  2. +13 −0 .github/dependabot.yml
  3. +2 −2 .github/workflows/release.yml
  4. +16 −12 .github/workflows/test.yml
  5. +19 −3 CHANGELOG.md
  6. +5 −5 README.md
  7. +1 −7 mkdocs.yml
  8. +1 −1 setup.cfg
  9. +39 −30 setup.py
  10. +9 −18 src/dotenv/cli.py
  11. +31 −25 src/dotenv/main.py
  12. +1 −1 src/dotenv/version.py
  13. +20 −23 tests/test_main.py
  14. +20 −20 tox.ini
18 changes: 18 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Security Policy

## Supported Versions

| Version | Supported |
| --------- | ------------------ |
| latest | :white_check_mark: |
| 0.x | :x: |

## Reporting a Vulnerability

If you believe you have identified a security issue with python-dotenv, please email
python-dotenv@saurabh-kumar.com. A maintainer will contact you acknowledging the report
and how to continue.

Be sure to include as much detail as necessary in your report. As with reporting normal
issues, a minimal reproducible example will help the maintainers address the issue faster.
If you are able, you may also include a fix for the issue generated with `git format-patch`.
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Keep GitHub Actions up to date with GitHub's Dependabot...
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
version: 2
updates:
- package-ecosystem: github-actions
directory: /
groups:
github-actions:
patterns:
- "*" # Group all Actions updates into a single larger pull request
schedule:
interval: weekly
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
28 changes: 16 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -7,24 +7,28 @@ jobs:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
max-parallel: 8
matrix:
os:
- ubuntu-latest
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", pypy3.9, pypy3.10]
python-version:
["3.9", "3.10", "3.11", "3.12", "3.13", pypy3.9, pypy3.10]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true

- name: Install dependencies
run:
python -m pip install --upgrade pip
pip install tox tox-gh-actions
- name: Upgrade pip
run: python -m pip install --upgrade pip

- name: Test with tox
run: tox
- name: Install dependencies
run: pip install tox tox-gh-actions

- name: Test with tox
run: tox
22 changes: 19 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,12 +5,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [1.1.0] - 2025-03-25

**Feature**
- Add support for python 3.13
- Enhance `dotenv run`, switch to `execvpe` for better resource management and signal handling ([#523]) by [@eekstunt]

**Fixed**
- `find_dotenv` and `load_dotenv` now correctly looks up at the current directory when running in debugger or pdb ([#553] by [@randomseed42])

**Misc**
- Drop support for Python 3.8

## [1.0.1] - 2024-01-23

**Fixed**

* Gracefully handle code which has been imported from a zipfile ([#456] by [@samwyma])
* Allow modules using load_dotenv to be reloaded when launched in a separate thread ([#497] by [@freddyaboulton])
* Allow modules using `load_dotenv` to be reloaded when launched in a separate thread ([#497] by [@freddyaboulton])
* Fix file not closed after deletion, handle error in the rewrite function ([#469] by [@Qwerty-133])

**Misc**
@@ -317,7 +330,7 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.5.1

- Fix find\_dotenv - it now start search from the file where this
- Fix `find_dotenv` - it now start search from the file where this
function is called from.

## 0.5.0
@@ -346,6 +359,8 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
[#466]: https://github.com/theskumar/python-dotenv/issues/466
[#454]: https://github.com/theskumar/python-dotenv/issues/454
[#474]: https://github.com/theskumar/python-dotenv/issues/474
[#523]: https://github.com/theskumar/python-dotenv/issues/523
[#553]: https://github.com/theskumar/python-dotenv/issues/553

[@alanjds]: https://github.com/alanjds
[@altendky]: https://github.com/altendky
@@ -356,6 +371,7 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
[@cjauvin]: https://github.com/cjauvin
[@eaf]: https://github.com/eaf
[@earlbread]: https://github.com/earlbread
[@eekstunt]: https://github.com/eekstunt
[@eggplants]: https://github.com/@eggplants
[@ekohl]: https://github.com/ekohl
[@elbehery95]: https://github.com/elbehery95
@@ -389,7 +405,7 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
[@x-yuri]: https://github.com/x-yuri
[@yannham]: https://github.com/yannham
[@zueve]: https://github.com/zueve

[@randomseed42]: https://github.com/zueve

[Unreleased]: https://github.com/theskumar/python-dotenv/compare/v1.0.1...HEAD
[1.0.1]: https://github.com/theskumar/python-dotenv/compare/v1.0.0...v1.0.1
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
[![Build Status][build_status_badge]][build_status_link]
[![PyPI version][pypi_badge]][pypi_link]

Python-dotenv reads key-value pairs from a `.env` file and can set them as environment
python-dotenv reads key-value pairs from a `.env` file and can set them as environment
variables. It helps in the development of applications following the
[12-factor](https://12factor.net/) principles.

@@ -29,20 +29,20 @@ If your application takes its configuration from environment variables, like a 1
application, launching it in development is not very practical because you have to set
those environment variables yourself.

To help you with that, you can add Python-dotenv to your application to make it load the
To help you with that, you can add python-dotenv to your application to make it load the
configuration from a `.env` file when it is present (e.g. in development) while remaining
configurable via the environment:

```python
from dotenv import load_dotenv

load_dotenv() # take environment variables from .env.
load_dotenv() # take environment variables

# Code of your application, which uses environment variables (e.g. from `os.environ` or
# `os.getenv`) as if they came from the actual environment.
```

By default, `load_dotenv` doesn't override existing environment variables.
By default, `load_dotenv` doesn't override existing environment variables and looks for a `.env` file in same directory as python script or searches for it incrementally higher up.

To configure the development environment, add a `.env` in the root directory of your
project:
@@ -201,7 +201,7 @@ empty string.

### Variable expansion

Python-dotenv can interpolate variables using POSIX variable expansion.
python-dotenv can interpolate variables using POSIX variable expansion.

With `load_dotenv(override=True)` or `dotenv_values()`, the value of a variable is the
first of the values defined in the following list:
8 changes: 1 addition & 7 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -13,13 +13,7 @@ markdown_extensions:
- mdx_truly_sane_lists

plugins:
- mkdocstrings:
handlers:
python:
rendering:
show_root_heading: yes
show_submodules: no
separate_signature: yes
- mkdocstrings
- search
nav:
- Home: index.md
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.0.0
current_version = 1.1.0
commit = True
tag = True

69 changes: 39 additions & 30 deletions setup.py
Original file line number Diff line number Diff line change
@@ -4,59 +4,68 @@
def read_files(files):
data = []
for file in files:
with open(file, encoding='utf-8') as f:
with open(file, encoding="utf-8") as f:
data.append(f.read())
return "\n".join(data)


long_description = read_files(['README.md', 'CHANGELOG.md'])
long_description = read_files(["README.md", "CHANGELOG.md"])

meta = {}
with open('./src/dotenv/version.py', encoding='utf-8') as f:
with open("./src/dotenv/version.py", encoding="utf-8") as f:
exec(f.read(), meta)

setup(
name="python-dotenv",
description="Read key-value pairs from a .env file and set them as environment variables",
long_description=long_description,
long_description_content_type='text/markdown',
version=meta['__version__'],
long_description_content_type="text/markdown",
version=meta["__version__"],
author="Saurabh Kumar",
author_email="me+github@saurabh-kumar.com",
url="https://github.com/theskumar/python-dotenv",
keywords=['environment variables', 'deployments', 'settings', 'env', 'dotenv',
'configurations', 'python'],
packages=['dotenv'],
package_dir={'': 'src'},
keywords=[
"environment variables",
"deployments",
"settings",
"env",
"dotenv",
"configurations",
"python",
],
packages=["dotenv"],
package_dir={"": "src"},
package_data={
'dotenv': ['py.typed'],
"dotenv": ["py.typed"],
},
python_requires=">=3.8",
python_requires=">=3.9",
extras_require={
'cli': ['click>=5.0', ],
"cli": [
"click>=5.0",
],
},
entry_points={
"console_scripts": [
"dotenv=dotenv.__main__:cli",
],
},
license='BSD-3-Clause',
license="BSD-3-Clause",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: Implementation :: PyPy',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Topic :: System :: Systems Administration',
'Topic :: Utilities',
'Environment :: Web Environment',
]
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: PyPy",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Topic :: System :: Systems Administration",
"Topic :: Utilities",
"Environment :: Web Environment",
],
)
27 changes: 9 additions & 18 deletions src/dotenv/cli.py
Original file line number Diff line number Diff line change
@@ -3,8 +3,7 @@
import shlex
import sys
from contextlib import contextmanager
from subprocess import Popen
from typing import Any, Dict, IO, Iterator, List
from typing import Any, Dict, IO, Iterator, List, Optional

try:
import click
@@ -17,7 +16,7 @@
from .version import __version__


def enumerate_env():
def enumerate_env() -> Optional[str]:
"""
Return a path for the ${pwd}/.env file.
@@ -161,14 +160,13 @@ def run(ctx: click.Context, override: bool, commandline: List[str]) -> None:
if not commandline:
click.echo('No command given.')
exit(1)
ret = run_command(commandline, dotenv_as_dict)
exit(ret)
run_command(commandline, dotenv_as_dict)


def run_command(command: List[str], env: Dict[str, str]) -> int:
"""Run command in sub process.
def run_command(command: List[str], env: Dict[str, str]) -> None:
"""Replace the current process with the specified command.
Runs the command in a sub process with the variables from `env`
Replaces the current process with the specified command and the variables from `env`
added in the current environment variables.
Parameters
@@ -180,20 +178,13 @@ def run_command(command: List[str], env: Dict[str, str]) -> int:
Returns
-------
int
The return code of the command
None
This function does not return any value. It replaces the current process with the new one.
"""
# copy the current environment variables and add the vales from
# `env`
cmd_env = os.environ.copy()
cmd_env.update(env)

p = Popen(command,
universal_newlines=True,
bufsize=0,
shell=False,
env=cmd_env)
_, _ = p.communicate()

return p.returncode
os.execvpe(command[0], args=command, env=cmd_env)
Loading