diff --git a/htmlcov/d_008d62399e2fcc76___init___py.html b/htmlcov/d_008d62399e2fcc76___init___py.html index 807ff2fd7..2644831d4 100644 --- a/htmlcov/d_008d62399e2fcc76___init___py.html +++ b/htmlcov/d_008d62399e2fcc76___init___py.html @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 8 statements   + 9 statements   - - - + + +

« prev     @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

+

+ « prev     + ^ index     + » next +       + coverage.py v6.5.0, + created at 2022-12-03 17:15 +0000 +

+ + + +
+
+ + + diff --git a/htmlcov/d_133056fd40ad78b4_test_node_py.html b/htmlcov/d_133056fd40ad78b4_test_node_py.html new file mode 100644 index 000000000..2be0e6b2f --- /dev/null +++ b/htmlcov/d_133056fd40ad78b4_test_node_py.html @@ -0,0 +1,358 @@ + + + + + Coverage for tests/test_node/test_node.py: 100% + + + + + +
+
+

+ Coverage for tests/test_node/test_node.py: + 100% +

+ +

+ 73 statements   + + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v6.5.0, + created at 2022-12-03 17:15 +0000 +

+ +
+
+
+

1import os 

+

2import sys 

+

3import shutil 

+

4import subprocess 

+

5from typing import cast 

+

6from pathlib import Path 

+

7 

+

8import pytest 

+

9from pytest_subprocess import FakeProcess 

+

10from prisma.cli import _node as node 

+

11from prisma.cli._node import Target 

+

12from prisma._config import Config 

+

13from prisma._compat import nodejs 

+

14 

+

15from ..utils import set_config 

+

16 

+

17 

+

18THIS_DIR = Path(__file__).parent 

+

19 

+

20parametrize_target = pytest.mark.parametrize('target', ['node', 'npm']) 

+

21 

+

22 

+

23def _assert_can_run_js(strategy: node.Node) -> None: 

+

24 proc = strategy.run( 

+

25 str(THIS_DIR.joinpath('test.js')), 

+

26 stdout=subprocess.PIPE, 

+

27 ) 

+

28 output = proc.stdout.decode('utf-8') 

+

29 assert output == 'Hello world!\n' 

+

30 

+

31 

+

32def _assert_can_run_npm(strategy: node.Node) -> None: 

+

33 assert strategy.target == 'npm' 

+

34 

+

35 proc = strategy.run('help', stdout=subprocess.PIPE) 

+

36 output = proc.stdout.decode('utf-8') 

+

37 

+

38 assert 'npm' in output 

+

39 

+

40 

+

41def assert_strategy(strategy: node.Node) -> None: 

+

42 if strategy.target == 'node': 

+

43 _assert_can_run_js(strategy) 

+

44 elif strategy.target == 'npm': 

+

45 _assert_can_run_npm(strategy) 

+

46 else: # pragma: no cover 

+

47 raise ValueError( 

+

48 f'No tests implemented for strategy target: {strategy.target}' 

+

49 ) 

+

50 

+

51 

+

52def test_resolve_bad_target() -> None: 

+

53 """resolve() raises a helpful error message when given an unknown target""" 

+

54 with pytest.raises( 

+

55 node.UnknownTargetError, 

+

56 match='Unknown target: foo; Valid choices are: node, npm', 

+

57 ): 

+

58 node.resolve(cast(node.Target, 'foo')) 

+

59 

+

60 

+

61@parametrize_target 

+

62@pytest.mark.skipif(nodejs is None, reason='nodejs-bin is not installed') 

+

63def test_nodejs_bin(target: Target) -> None: 

+

64 """When `nodejs-bin` is installed, it is resolved to and can be successfully used""" 

+

65 with set_config( 

+

66 Config.parse( 

+

67 use_nodejs_bin=True, 

+

68 use_global_node=False, 

+

69 ) 

+

70 ): 

+

71 strategy = node.resolve(target) 

+

72 assert strategy.resolver == 'nodejs-bin' 

+

73 assert_strategy(strategy) 

+

74 

+

75 

+

76@parametrize_target 

+

77@pytest.mark.skipif( 

+

78 shutil.which('node') is None, 

+

79 reason='Node is not installed globally', 

+

80) 

+

81def test_resolves_binary_node(target: Target) -> None: 

+

82 """When `node` is installed globally, it is resolved to and can be successfully used""" 

+

83 with set_config( 

+

84 Config.parse( 

+

85 use_nodejs_bin=False, 

+

86 use_global_node=True, 

+

87 ) 

+

88 ): 

+

89 strategy = node.resolve(target) 

+

90 assert strategy.resolver == 'global' 

+

91 assert_strategy(strategy) 

+

92 

+

93 with set_config( 

+

94 Config.parse( 

+

95 use_nodejs_bin=False, 

+

96 use_global_node=False, 

+

97 ) 

+

98 ): 

+

99 strategy = node.resolve(target) 

+

100 assert strategy.resolver == 'nodeenv' 

+

101 assert_strategy(strategy) 

+

102 

+

103 

+

104@parametrize_target 

+

105def test_nodeenv(target: Target) -> None: 

+

106 """When `nodejs-bin` and global `node` is not installed / configured to use, `nodeenv` is resolved to and can be successfully used""" 

+

107 with set_config( 

+

108 Config.parse( 

+

109 use_nodejs_bin=False, 

+

110 use_global_node=False, 

+

111 ) 

+

112 ): 

+

113 strategy = node.resolve(target) 

+

114 assert strategy.resolver == 'nodeenv' 

+

115 assert_strategy(strategy) 

+

116 

+

117 

+

118@parametrize_target 

+

119def test_nodeenv_extra_args( 

+

120 target: Target, 

+

121 tmp_path: Path, 

+

122 fake_process: FakeProcess, 

+

123) -> None: 

+

124 """The config option `nodeenv_extra_args` is respected""" 

+

125 cache_dir = tmp_path / 'nodeenv' 

+

126 

+

127 fake_process.register_subprocess( 

+

128 [sys.executable, '-m', 'nodeenv', str(cache_dir), '--my-extra-flag'], 

+

129 returncode=403, 

+

130 ) 

+

131 

+

132 with set_config( 

+

133 Config.parse( 

+

134 use_nodejs_bin=False, 

+

135 use_global_node=False, 

+

136 nodeenv_extra_args=['--my-extra-flag'], 

+

137 nodeenv_cache_dir=cache_dir, 

+

138 ) 

+

139 ): 

+

140 with pytest.raises(subprocess.CalledProcessError) as exc: 

+

141 node.resolve(target) 

+

142 

+

143 assert exc.value.returncode == 403 

+

144 

+

145 

+

146def test_update_path_env() -> None: 

+

147 """The _update_path_env() function correctly appends the target binary path to the PATH environment variable""" 

+

148 target = THIS_DIR / 'bin' 

+

149 if not target.exists(): # pragma: no branch 

+

150 target.mkdir() 

+

151 

+

152 sep = os.pathsep 

+

153 

+

154 # known PATH separators - please update if need be 

+

155 assert sep in {':', ';'} 

+

156 

+

157 # no env 

+

158 env = node._update_path_env(env=None, target_bin=target) 

+

159 assert env['PATH'].startswith(f'{target.absolute()}{sep}') 

+

160 

+

161 # env without PATH 

+

162 env = node._update_path_env( 

+

163 env={'FOO': 'bar'}, 

+

164 target_bin=target, 

+

165 ) 

+

166 assert env['PATH'].startswith(f'{target.absolute()}{sep}') 

+

167 

+

168 # env with empty PATH 

+

169 env = node._update_path_env( 

+

170 env={'PATH': ''}, 

+

171 target_bin=target, 

+

172 ) 

+

173 assert env['PATH'].startswith(f'{target.absolute()}{sep}') 

+

174 

+

175 # env with set PATH without the separator postfix 

+

176 env = node._update_path_env( 

+

177 env={'PATH': '/foo'}, 

+

178 target_bin=target, 

+

179 ) 

+

180 assert env['PATH'] == f'{target.absolute()}{sep}/foo' 

+

181 

+

182 # env with set PATH with the separator as a prefix 

+

183 env = node._update_path_env( 

+

184 env={'PATH': f'{sep}/foo'}, 

+

185 target_bin=target, 

+

186 ) 

+

187 assert env['PATH'] == f'{target.absolute()}{sep}/foo' 

+

188 

+

189 # returned env included non PATH environment variables 

+

190 env = node._update_path_env( 

+

191 env={'PATH': '/foo', 'FOO': 'bar'}, 

+

192 target_bin=target, 

+

193 ) 

+

194 assert env['FOO'] == 'bar' 

+

195 assert env['PATH'] == f'{target.absolute()}{sep}/foo' 

+

196 

+

197 # accepts a custom path separator 

+

198 env = node._update_path_env( 

+

199 env={'PATH': '/foo'}, 

+

200 target_bin=target, 

+

201 sep='---', 

+

202 ) 

+

203 assert env['PATH'] == f'{target.absolute()}---/foo' 

+

204 

+

205 

+

206@parametrize_target 

+

207@pytest.mark.skipif( 

+

208 shutil.which('node') is None, 

+

209 reason='Node is not installed globally', 

+

210) 

+

211def test_node_version(target: Target, fake_process: FakeProcess) -> None: 

+

212 """The node version can be detected properly and correctly constrained to our minimum required version""" 

+

213 

+

214 def _register_process(stdout: str) -> None: 

+

215 # register the same process twice as we will call it twice 

+

216 # in our assertions and fake_process consumes called processes 

+

217 for _ in range(2): 

+

218 fake_process.register_subprocess( 

+

219 [str(path), '--version'], stdout=stdout 

+

220 ) 

+

221 

+

222 which = shutil.which(target) 

+

223 assert which is not None 

+

224 

+

225 path = Path(which) 

+

226 

+

227 _register_process('v1.3.4') 

+

228 version = node._get_binary_version(target, path) 

+

229 assert version == (1, 3) 

+

230 assert node._should_use_binary(target, path) is False 

+

231 

+

232 _register_process('v1.32433') 

+

233 version = node._get_binary_version(target, path) 

+

234 assert version == (1, 32433) 

+

235 assert node._should_use_binary(target, path) is False 

+

236 

+

237 _register_process('v16.15.a4') 

+

238 version = node._get_binary_version(target, path) 

+

239 assert version == (16, 15) 

+

240 assert node._should_use_binary(target, path) is True 

+

241 

+

242 _register_process('v14.17.1') 

+

243 version = node._get_binary_version(target, path) 

+

244 assert version == (14, 17) 

+

245 assert node._should_use_binary(target, path) is True 

+

246 

+

247 _register_process('14.17.1') 

+

248 version = node._get_binary_version(target, path) 

+

249 assert version == (14, 17) 

+

250 assert node._should_use_binary(target, path) is True 

+

251 

+

252 

+

253def test_should_use_binary_unknown_target() -> None: 

+

254 """The UnknownTargetError() is raised by the _should_use_binary() function given an invalid target""" 

+

255 with pytest.raises(node.UnknownTargetError): 

+

256 node._should_use_binary( 

+

257 target='foo', # type: ignore 

+

258 path=Path.cwd(), 

+

259 ) 

+
+ + + diff --git a/htmlcov/d_1bffdd9b423b28e3___init___py.html b/htmlcov/d_1bffdd9b423b28e3___init___py.html index c1195a2fc..43abb0e0d 100644 --- a/htmlcov/d_1bffdd9b423b28e3___init___py.html +++ b/htmlcov/d_1bffdd9b423b28e3___init___py.html @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 56 statements   - + 60 statements   + @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 54 statements   - + 50 statements   + @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 35 statements   - + 13 statements   + @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

+

+ « prev     + ^ index     + » next +       + coverage.py v6.5.0, + created at 2022-12-03 17:15 +0000 +

+ + + +
+

1from pathlib import Path 

+

2 

+

3from prisma.cli import prisma 

+

4from prisma._config import Config 

+

5 

+

6from ..utils import set_config 

+

7 

+

8 

+

9def test_package_json_in_parent_dir(tmp_path: Path) -> None: 

+

10 """The CLI can be installed successfully when there is a `package.json` file 

+

11 in a parent directory. 

+

12 """ 

+

13 tmp_path.joinpath('package.json').write_text('{"name": "prisma-binaries"}') 

+

14 cache_dir = tmp_path / 'foo' / 'bar' 

+

15 

+

16 with set_config( 

+

17 Config.parse( 

+

18 binary_cache_dir=cache_dir, 

+

19 ) 

+

20 ): 

+

21 assert prisma.run(['-v']) == 0 

+
+ + + diff --git a/htmlcov/d_2b0bd9b783c90ea9_test_utils_py.html b/htmlcov/d_2b0bd9b783c90ea9_test_utils_py.html index 5e712d1e5..99dc8a318 100644 --- a/htmlcov/d_2b0bd9b783c90ea9_test_utils_py.html +++ b/htmlcov/d_2b0bd9b783c90ea9_test_utils_py.html @@ -62,12 +62,12 @@

- « prev     + « prev     ^ index     » next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 119 statements   - + 120 statements   + @@ -67,7 +67,7 @@

» next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

- 3 statements   - + 1 statements   + @@ -64,10 +64,10 @@

« prev     ^ index     - » next + » next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000

-

- « prev     - ^ index     - » next -       - coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 -

- - - -
-

1# -*- coding: utf-8 -*- 

-

2 

-

3import logging 

-

4from pathlib import Path 

-

5from typing import Optional, List 

-

6 

-

7import click 

-

8 

-

9from .binary import Binary 

-

10from .engine import Engine 

-

11from .constants import PRISMA_CLI_NAME 

-

12from .. import config 

-

13 

-

14 

-

15__all__ = ( 

-

16 'ENGINES', 

-

17 'BINARIES', 

-

18 'ensure_cached', 

-

19 'remove_all', 

-

20) 

-

21 

-

22log: logging.Logger = logging.getLogger(__name__) 

-

23 

-

24ENGINES = [ 

-

25 Engine(name='query-engine', env='PRISMA_QUERY_ENGINE_BINARY'), 

-

26 Engine(name='migration-engine', env='PRISMA_MIGRATION_ENGINE_BINARY'), 

-

27 Engine( 

-

28 name='introspection-engine', env='PRISMA_INTROSPECTION_ENGINE_BINARY' 

-

29 ), 

-

30 Engine(name='prisma-fmt', env='PRISMA_FMT_BINARY'), 

-

31] 

-

32 

-

33BINARIES: List[Binary] = [ 

-

34 *ENGINES, 

-

35 Binary(name=PRISMA_CLI_NAME, env='PRISMA_CLI_BINARY'), 

-

36] 

-

37 

-

38 

-

39def ensure_cached() -> Path: 

-

40 binaries: List[Binary] = [] 

-

41 for binary in BINARIES: 

-

42 path = binary.path 

-

43 if path.exists(): 

-

44 log.debug('%s cached at %s', binary.name, path) 

-

45 else: 

-

46 log.debug('%s not cached at %s', binary.name, path) 

-

47 binaries.append(binary) 

-

48 

-

49 if not binaries: 

-

50 log.debug('All binaries are cached') 

-

51 return config.binary_cache_dir 

-

52 

-

53 def show_item(item: Optional[Binary]) -> str: 

-

54 if item is not None: 

-

55 return binary.name 

-

56 return '' 

-

57 

-

58 with click.progressbar( 

-

59 binaries, 

-

60 label='Downloading binaries', 

-

61 fill_char=click.style('#', fg='yellow'), 

-

62 item_show_func=show_item, 

-

63 ) as iterator: 

-

64 for binary in iterator: 

-

65 binary.download() 

-

66 

-

67 return config.binary_cache_dir 

-

68 

-

69 

-

70def remove_all() -> None: 

-

71 """Remove all downloaded binaries""" 

-

72 for binary in BINARIES: 

-

73 if binary.path.exists(): 

-

74 binary.path.unlink() 

-
- - - diff --git a/htmlcov/d_8398f7b9ccc3cdc0_binary_py.html b/htmlcov/d_8398f7b9ccc3cdc0_binary_py.html deleted file mode 100644 index c882d6157..000000000 --- a/htmlcov/d_8398f7b9ccc3cdc0_binary_py.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Coverage for src/prisma/binaries/binary.py: 100% - - - - - -
-
-

- Coverage for src/prisma/binaries/binary.py: - 100% -

- -

- 31 statements   - - - - -

-

- « prev     - ^ index     - » next -       - coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 -

- -
-
-
-

1import os 

-

2import logging 

-

3from pathlib import Path 

-

4from pydantic import BaseModel 

-

5 

-

6from . import platform 

-

7from .utils import download 

-

8from .. import config 

-

9 

-

10 

-

11__all__ = ('Binary',) 

-

12 

-

13log: logging.Logger = logging.getLogger(__name__) 

-

14 

-

15 

-

16class Binary(BaseModel): 

-

17 name: str 

-

18 env: str 

-

19 

-

20 def download(self) -> None: 

-

21 # TODO: respect schema binary options 

-

22 url = self.url 

-

23 dest = self.path 

-

24 

-

25 if dest.exists(): 

-

26 log.debug('%s is cached, skipping download', self.name) 

-

27 return 

-

28 

-

29 log.debug('Downloading from %s to %s', url, dest) 

-

30 download(url, str(dest.absolute())) 

-

31 log.debug('Downloaded %s to %s', self.name, dest.absolute()) 

-

32 

-

33 @property 

-

34 def url(self) -> str: 

-

35 return platform.check_for_extension(config.prisma_url).format( 

-

36 version=config.prisma_version, platform=platform.name() 

-

37 ) 

-

38 

-

39 @property 

-

40 def path(self) -> Path: 

-

41 env = os.environ.get(self.env) 

-

42 if env is not None: 

-

43 log.debug( 

-

44 'Using environment variable location: %s for %s', 

-

45 env, 

-

46 self.name, 

-

47 ) 

-

48 return Path(env) 

-

49 

-

50 return config.binary_cache_dir.joinpath( 

-

51 platform.check_for_extension(self.name) 

-

52 ) 

-
- - - diff --git a/htmlcov/d_8398f7b9ccc3cdc0_constants_py.html b/htmlcov/d_8398f7b9ccc3cdc0_constants_py.html index c64ebd3af..6aa928541 100644 --- a/htmlcov/d_8398f7b9ccc3cdc0_constants_py.html +++ b/htmlcov/d_8398f7b9ccc3cdc0_constants_py.html @@ -62,12 +62,12 @@

- « prev     + « prev     ^ index     - » next + » next       coverage.py v6.5.0, - created at 2022-12-01 03:19 +0000 + created at 2022-12-03 17:15 +0000