11import io
22import logging
33import os
4+ import stat
45import sys
56import textwrap
67from unittest import mock
78
89import pytest
9- import sh
1010
1111import dotenv
1212
13+ if not sys .platform .startswith ("win" ):
14+ import sh
15+
1316
1417def test_set_key_no_file (tmp_path ):
1518 nx_path = tmp_path / "nx"
@@ -62,15 +65,25 @@ def test_set_key_encoding(dotenv_path):
6265
6366
6467@pytest .mark .skipif (
65- os .geteuid () == 0 , reason = "Root user can access files even with 000 permissions."
68+ not sys .platform .startswith ("win" ) and os .geteuid () == 0 ,
69+ reason = "Root user can access files even with 000 permissions." ,
6670)
6771def test_set_key_permission_error (dotenv_path ):
68- dotenv_path .chmod (0o000 )
72+ if sys .platform .startswith ("win" ):
73+ # On Windows, make file read-only
74+ dotenv_path .chmod (stat .S_IREAD )
75+ else :
76+ # On Unix, remove all permissions
77+ dotenv_path .chmod (0o000 )
6978
7079 with pytest .raises (PermissionError ):
7180 dotenv .set_key (dotenv_path , "a" , "b" )
7281
73- dotenv_path .chmod (0o600 )
82+ # Restore permissions
83+ if sys .platform .startswith ("win" ):
84+ dotenv_path .chmod (stat .S_IWRITE | stat .S_IREAD )
85+ else :
86+ dotenv_path .chmod (0o600 )
7487 assert dotenv_path .read_text () == ""
7588
7689
@@ -170,16 +183,6 @@ def test_unset_encoding(dotenv_path):
170183 assert dotenv_path .read_text (encoding = encoding ) == ""
171184
172185
173- @pytest .mark .skipif (
174- os .geteuid () == 0 , reason = "Root user can access files even with 000 permissions."
175- )
176- def test_set_key_unauthorized_file (dotenv_path ):
177- dotenv_path .chmod (0o000 )
178-
179- with pytest .raises (PermissionError ):
180- dotenv .set_key (dotenv_path , "a" , "x" )
181-
182-
183186def test_unset_non_existent_file (tmp_path ):
184187 nx_path = tmp_path / "nx"
185188 logger = logging .getLogger ("dotenv.main" )
@@ -312,6 +315,9 @@ def test_load_dotenv_disabled_notification(dotenv_path, flag_value):
312315 )
313316
314317
318+ @pytest .mark .skipif (
319+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
320+ )
315321@pytest .mark .parametrize (
316322 "flag_value" ,
317323 [
@@ -395,6 +401,9 @@ def test_load_dotenv_no_file_verbose():
395401 )
396402
397403
404+ @pytest .mark .skipif (
405+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
406+ )
398407@mock .patch .dict (os .environ , {"a" : "c" }, clear = True )
399408def test_load_dotenv_existing_variable_no_override (dotenv_path ):
400409 dotenv_path .write_text ("a=b" )
@@ -405,6 +414,9 @@ def test_load_dotenv_existing_variable_no_override(dotenv_path):
405414 assert os .environ == {"a" : "c" }
406415
407416
417+ @pytest .mark .skipif (
418+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
419+ )
408420@mock .patch .dict (os .environ , {"a" : "c" }, clear = True )
409421def test_load_dotenv_existing_variable_override (dotenv_path ):
410422 dotenv_path .write_text ("a=b" )
@@ -415,6 +427,9 @@ def test_load_dotenv_existing_variable_override(dotenv_path):
415427 assert os .environ == {"a" : "b" }
416428
417429
430+ @pytest .mark .skipif (
431+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
432+ )
418433@mock .patch .dict (os .environ , {"a" : "c" }, clear = True )
419434def test_load_dotenv_redefine_var_used_in_file_no_override (dotenv_path ):
420435 dotenv_path .write_text ('a=b\n d="${a}"' )
@@ -425,6 +440,9 @@ def test_load_dotenv_redefine_var_used_in_file_no_override(dotenv_path):
425440 assert os .environ == {"a" : "c" , "d" : "c" }
426441
427442
443+ @pytest .mark .skipif (
444+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
445+ )
428446@mock .patch .dict (os .environ , {"a" : "c" }, clear = True )
429447def test_load_dotenv_redefine_var_used_in_file_with_override (dotenv_path ):
430448 dotenv_path .write_text ('a=b\n d="${a}"' )
@@ -435,6 +453,9 @@ def test_load_dotenv_redefine_var_used_in_file_with_override(dotenv_path):
435453 assert os .environ == {"a" : "b" , "d" : "b" }
436454
437455
456+ @pytest .mark .skipif (
457+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
458+ )
438459@mock .patch .dict (os .environ , {}, clear = True )
439460def test_load_dotenv_string_io_utf_8 ():
440461 stream = io .StringIO ("a=à" )
@@ -456,6 +477,9 @@ def test_load_dotenv_file_stream(dotenv_path):
456477 assert os .environ == {"a" : "b" }
457478
458479
480+ @pytest .mark .skipif (
481+ sys .platform .startswith ("win" ), reason = "sh module doesn't support Windows"
482+ )
459483def test_load_dotenv_in_current_dir (tmp_path ):
460484 dotenv_path = tmp_path / ".env"
461485 dotenv_path .write_bytes (b"a=b" )
@@ -484,6 +508,9 @@ def test_dotenv_values_file(dotenv_path):
484508 assert result == {"a" : "b" }
485509
486510
511+ @pytest .mark .skipif (
512+ sys .platform .startswith ("win" ), reason = "This test assumes case-sensitive variables"
513+ )
487514@pytest .mark .parametrize (
488515 "env,string,interpolate,expected" ,
489516 [
0 commit comments