Skip to content

Commit 76f8bc3

Browse files
authored
Merge pull request #35 from swansonk14/windows-tests
Successful attempt to fix windows tests
2 parents 59458ff + d3fac95 commit 76f8bc3

File tree

7 files changed

+99
-56
lines changed

7 files changed

+99
-56
lines changed

.github/workflows/tap-code-coverage.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ name: code-coverage
22
on:
33
push:
44
branches: [ master ]
5-
pull_request:
6-
branches: [ master ]
75
jobs:
86
run:
97
runs-on: ubuntu-latest

.github/workflows/tap-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
runs-on: ${{ matrix.os }}
1616
strategy:
1717
matrix:
18-
os: [ubuntu-latest, macos-latest]
18+
os: [ubuntu-latest, macos-latest, windows-latest]
1919
python-version: [3.6, 3.7, 3.8, 3.9]
2020

2121
steps:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/typed-argument-parser)](https://badge.fury.io/py/typed-argument-parser)
88
[![PyPI version](https://badge.fury.io/py/typed-argument-parser.svg)](https://badge.fury.io/py/typed-argument-parser)
99
[![Build Status](https://github.com/swansonk14/typed-argument-parser/workflows/tests/badge.svg)](https://github.com/swansonk14/typed-argument-parser)
10-
[![license](https://img.shields.io/github/license/swansonk14/typed-argument-parser.svg)](https://github.com/swansonk14/typed-argument-parser/blob/master/LICENSE.txt)
1110
[![codecov](https://codecov.io/gh/swansonk14/typed-argument-parser/branch/master/graph/badge.svg)](https://codecov.io/gh/swansonk14/typed-argument-parser)
11+
[![license](https://img.shields.io/github/license/swansonk14/typed-argument-parser.svg)](https://github.com/swansonk14/typed-argument-parser/blob/master/LICENSE.txt)
1212

1313
Tap is a typed modernization of Python's [argparse](https://docs.python.org/3/library/argparse.html) library.
1414

tap/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def get_git_url(commit_hash: bool = True) -> str:
9090

9191
if commit_hash:
9292
# Add tree and hash of current commit
93-
url = os.path.join(url, 'tree', get_git_hash())
93+
url = f'{url}/tree/{get_git_hash()}'
9494

9595
return url
9696

tests/test_integration.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from copy import deepcopy
2+
import os
23
import sys
3-
from tempfile import NamedTemporaryFile
4+
from tempfile import TemporaryDirectory
45
from typing import Any, List, Optional, Set, Tuple
56
from typing_extensions import Literal
67
import unittest
@@ -1023,10 +1024,11 @@ class SimpleSaveLoadTap(Tap):
10231024

10241025
args = SimpleSaveLoadTap().parse_args(['--a', 'hi'])
10251026

1026-
with NamedTemporaryFile() as f:
1027-
args.save(f.name)
1027+
with TemporaryDirectory() as temp_dir:
1028+
fname = os.path.join(temp_dir, 'args.json')
1029+
args.save(fname)
10281030
new_args = SimpleSaveLoadTap()
1029-
new_args.load(f.name)
1031+
new_args.load(fname)
10301032

10311033
output = {'a': 'hi', 'b': 1, 'c': True}
10321034
self.assertEqual(output, new_args.as_dict())
@@ -1037,9 +1039,10 @@ class SaveLoadReturnTap(Tap):
10371039

10381040
args = SaveLoadReturnTap().parse_args(['--a', 'hi'])
10391041

1040-
with NamedTemporaryFile() as f:
1041-
args.save(f.name)
1042-
new_args = SaveLoadReturnTap().load(f.name)
1042+
with TemporaryDirectory() as temp_dir:
1043+
fname = os.path.join(temp_dir, 'args.json')
1044+
args.save(fname)
1045+
new_args = SaveLoadReturnTap().load(fname)
10431046

10441047
output = {'a': 'hi'}
10451048
self.assertEqual(output, new_args.as_dict())
@@ -1059,10 +1062,11 @@ def configure(self) -> None:
10591062

10601063
args = ComplexSaveLoadTap().parse_args(['--a', 'hi', '--d', 'a', 'b', '--e', '7', '--g', 'tapper'])
10611064

1062-
with NamedTemporaryFile() as f:
1063-
args.save(f.name)
1065+
with TemporaryDirectory() as temp_dir:
1066+
fname = os.path.join(temp_dir, 'args.json')
1067+
args.save(fname)
10641068
new_args = ComplexSaveLoadTap()
1065-
new_args.load(f.name)
1069+
new_args.load(fname)
10661070

10671071
output = {'e': 7, 'f': {1}, 'd': ('a', 'b'), 'c': True, 'a': 'hi', 'b': 1, 'g': Person('tapper')}
10681072
self.assertEqual(output, new_args.as_dict())
@@ -1094,14 +1098,15 @@ def process_args(self) -> None:
10941098

10951099
args = PropertySaveLoadTap().parse_args([])
10961100

1097-
with NamedTemporaryFile() as f:
1098-
args.save(f.name)
1101+
with TemporaryDirectory() as temp_dir:
1102+
fname = os.path.join(temp_dir, 'args.json')
1103+
args.save(fname)
10991104
new_args = PropertySaveLoadTap()
11001105

11011106
with self.assertRaises(AttributeError):
1102-
new_args.load(f.name) # because trying to set unsettable prop1
1107+
new_args.load(fname) # because trying to set unsettable prop1
11031108

1104-
new_args.load(f.name, skip_unsettable=True)
1109+
new_args.load(fname, skip_unsettable=True)
11051110

11061111
output = {'a': 'hello', 'prop1': 1, 'prop2': 'bye'}
11071112
self.assertEqual(output, new_args.as_dict())

tests/test_load_config_files.py

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import os
12
import sys
2-
from tempfile import NamedTemporaryFile
3+
from tempfile import TemporaryDirectory
34
import unittest
45
from unittest import TestCase
56

@@ -26,10 +27,13 @@ class SimpleTap(Tap):
2627
a: int
2728
b: str = 'b'
2829

29-
with NamedTemporaryFile() as f:
30-
f.write(b'--a 1')
31-
f.flush()
32-
args = SimpleTap(config_files=[f.name]).parse_args([])
30+
with TemporaryDirectory() as temp_dir:
31+
fname = os.path.join(temp_dir, 'config.txt')
32+
33+
with open(fname, 'w') as f:
34+
f.write('--a 1')
35+
36+
args = SimpleTap(config_files=[fname]).parse_args([])
3337

3438
self.assertEqual(args.a, 1)
3539
self.assertEqual(args.b, 'b')
@@ -39,10 +43,13 @@ class SimpleOverwritingTap(Tap):
3943
a: int
4044
b: str = 'b'
4145

42-
with NamedTemporaryFile() as f:
43-
f.write(b'--a 1 --b two')
44-
f.flush()
45-
args = SimpleOverwritingTap(config_files=[f.name]).parse_args('--a 2'.split())
46+
with TemporaryDirectory() as temp_dir:
47+
fname = os.path.join(temp_dir, 'config.txt')
48+
49+
with open(fname, 'w') as f:
50+
f.write('--a 1 --b two')
51+
52+
args = SimpleOverwritingTap(config_files=[fname]).parse_args('--a 2'.split())
4653

4754
self.assertEqual(args.a, 2)
4855
self.assertEqual(args.b, 'two')
@@ -52,10 +59,13 @@ class KnownOnlyTap(Tap):
5259
a: int
5360
b: str = 'b'
5461

55-
with NamedTemporaryFile() as f:
56-
f.write(b'--a 1 --c seeNothing')
57-
f.flush()
58-
args = KnownOnlyTap(config_files=[f.name]).parse_args([], known_only=True)
62+
with TemporaryDirectory() as temp_dir:
63+
fname = os.path.join(temp_dir, 'config.txt')
64+
65+
with open(fname, 'w') as f:
66+
f.write('--a 1 --c seeNothing')
67+
68+
args = KnownOnlyTap(config_files=[fname]).parse_args([], known_only=True)
5969

6070
self.assertEqual(args.a, 1)
6171
self.assertEqual(args.b, 'b')
@@ -66,23 +76,28 @@ class KnownOnlyTap(Tap):
6676
a: int
6777
b: str = 'b'
6878

69-
with NamedTemporaryFile() as f, self.assertRaises(SystemExit):
79+
with TemporaryDirectory() as temp_dir, self.assertRaises(SystemExit):
7080
sys.stderr = self.dev_null
71-
f.write(b'--b fore')
72-
f.flush()
73-
KnownOnlyTap(config_files=[f.name]).parse_args([])
81+
fname = os.path.join(temp_dir, 'config.txt')
82+
83+
with open(fname, 'w') as f:
84+
f.write('--b fore')
85+
86+
KnownOnlyTap(config_files=[fname]).parse_args([])
7487

7588
def test_multiple_configs(self) -> None:
7689
class MultipleTap(Tap):
7790
a: int
7891
b: str = 'b'
7992

80-
with NamedTemporaryFile() as f1, NamedTemporaryFile() as f2:
81-
f1.write(b'--b two')
82-
f1.flush()
83-
f2.write(b'--a 1')
84-
f2.flush()
85-
args = MultipleTap(config_files=[f1.name, f2.name]).parse_args([])
93+
with TemporaryDirectory() as temp_dir:
94+
fname1, fname2 = os.path.join(temp_dir, 'config1.txt'), os.path.join(temp_dir, 'config2.txt')
95+
96+
with open(fname1, 'w') as f1, open(fname2, 'w') as f2:
97+
f1.write('--b two')
98+
f2.write('--a 1')
99+
100+
args = MultipleTap(config_files=[fname1, fname2]).parse_args([])
86101

87102
self.assertEqual(args.a, 1)
88103
self.assertEqual(args.b, 'two')
@@ -93,12 +108,14 @@ class MultipleOverwritingTap(Tap):
93108
b: str = 'b'
94109
c: str = 'c'
95110

96-
with NamedTemporaryFile() as f1, NamedTemporaryFile() as f2:
97-
f1.write(b'--a 1 --b two')
98-
f1.flush()
99-
f2.write(b'--a 2 --c see')
100-
f2.flush()
101-
args = MultipleOverwritingTap(config_files=[f1.name, f2.name]).parse_args('--b four'.split())
111+
with TemporaryDirectory() as temp_dir:
112+
fname1, fname2 = os.path.join(temp_dir, 'config1.txt'), os.path.join(temp_dir, 'config2.txt')
113+
114+
with open(fname1, 'w') as f1, open(fname2, 'w') as f2:
115+
f1.write('--a 1 --b two')
116+
f2.write('--a 2 --c see')
117+
118+
args = MultipleOverwritingTap(config_files=[fname1, fname2]).parse_args('--b four'.split())
102119

103120
self.assertEqual(args.a, 2)
104121
self.assertEqual(args.b, 'four')
@@ -109,11 +126,14 @@ class JunkConfigTap(Tap):
109126
a: int
110127
b: str = 'b'
111128

112-
with NamedTemporaryFile() as f1, self.assertRaises(SystemExit):
129+
with TemporaryDirectory() as temp_dir, self.assertRaises(SystemExit):
113130
sys.stderr = self.dev_null
114-
f1.write(b'is not a file that can reasonably be parsed')
115-
f1.flush()
116-
JunkConfigTap(config_files=[f1.name]).parse_args()
131+
fname = os.path.join(temp_dir, 'config.txt')
132+
133+
with open(fname, 'w') as f:
134+
f.write('is not a file that can reasonably be parsed')
135+
136+
JunkConfigTap(config_files=[fname]).parse_args()
117137

118138

119139
if __name__ == '__main__':

tests/test_utils.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from collections import OrderedDict
22
import json
33
import os
4+
import platform
45
import subprocess
56
from tempfile import TemporaryDirectory
67
from typing import Any, Callable, List, Dict, Set, Tuple, Union
@@ -28,6 +29,7 @@
2829
class GitTests(TestCase):
2930
def setUp(self) -> None:
3031
self.temp_dir = TemporaryDirectory()
32+
self.prev_dir = os.getcwd()
3133
os.chdir(self.temp_dir.name)
3234
subprocess.check_output(['git', 'init'])
3335
self.url = 'https://github.com/test_account/test_repo'
@@ -37,6 +39,13 @@ def setUp(self) -> None:
3739
subprocess.check_output(['git', 'commit', '-m', 'Initial commit'])
3840

3941
def tearDown(self) -> None:
42+
os.chdir(self.prev_dir)
43+
44+
# Add permissions to temporary directory to enable cleanup in Windows
45+
for root, dirs, files in os.walk(self.temp_dir.name):
46+
for name in dirs + files:
47+
os.chmod(os.path.join(root, name), 0o777)
48+
4049
self.temp_dir.cleanup()
4150

4251
def test_has_git_true(self) -> None:
@@ -46,14 +55,25 @@ def test_has_git_false(self) -> None:
4655
with TemporaryDirectory() as temp_dir_no_git:
4756
os.chdir(temp_dir_no_git)
4857
self.assertFalse(has_git())
49-
os.chdir(self.temp_dir.name)
58+
os.chdir(self.temp_dir.name)
5059

60+
# TODO: fix this test on Windows
61+
@unittest.skipIf(platform.system() == 'Windows', 'Inconsistent user path on Windows in GitHub Actions')
5162
def test_get_git_root(self) -> None:
52-
self.assertTrue(get_git_root() in f'/private{self.temp_dir.name}')
63+
# Ideally should be self.temp_dir.name == get_git_root() but the OS may add a prefix like /private
64+
self.assertTrue(get_git_root().endswith(self.temp_dir.name))
5365

66+
# TODO: fix this test on Windows
67+
@unittest.skipIf(platform.system() == 'Windows', 'Inconsistent user path on Windows in GitHub Actions')
5468
def test_get_git_root_subdir(self) -> None:
55-
os.makedirs(os.path.join(self.temp_dir.name, 'subdir'))
56-
self.assertTrue(get_git_root() in f'/private{self.temp_dir.name}')
69+
subdir = os.path.join(self.temp_dir.name, 'subdir')
70+
os.makedirs(subdir)
71+
os.chdir(subdir)
72+
73+
# Ideally should be self.temp_dir.name == get_git_root() but the OS may add a prefix like /private
74+
self.assertTrue(get_git_root().endswith(self.temp_dir.name))
75+
76+
os.chdir(self.temp_dir.name)
5777

5878
def test_get_git_url_https(self) -> None:
5979
self.assertEqual(get_git_url(commit_hash=False), self.url)

0 commit comments

Comments
 (0)