* allowing arbitrary keys for xspecs but adding some sanity checks to xspec-parsing and makegateway.
* fixing a python3 IO issue - we need to retain sys.stdout/stdin references to keep the underlying byte stream open. --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									1b97d06a09
								
							
						
					
					
						commit
						e3b34c9da3
					
				|  | @ -226,7 +226,7 @@ class PopenGateway(PopenCmdGateway): | ||||||
|         s = "\n".join([extra,  |         s = "\n".join([extra,  | ||||||
|             "import sys ; sys.path[:0] = %r" % (plist,),  |             "import sys ; sys.path[:0] = %r" % (plist,),  | ||||||
|             "import os ; os.environ['PYTHONPATH'] = %r" % ppath,  |             "import os ; os.environ['PYTHONPATH'] = %r" % ppath,  | ||||||
|             str(py.code.Source(stdouterrin_setnull)),  |             inspect.getsource(stdouterrin_setnull),  | ||||||
|             "stdouterrin_setnull()",  |             "stdouterrin_setnull()",  | ||||||
|             "" |             "" | ||||||
|             ]) |             ]) | ||||||
|  |  | ||||||
|  | @ -119,10 +119,6 @@ sys.stdin = tempfile.TemporaryFile('r') | ||||||
| 
 | 
 | ||||||
|     def __init__(self, outfile, infile): |     def __init__(self, outfile, infile): | ||||||
|         # we need raw byte streams  |         # we need raw byte streams  | ||||||
|         if hasattr(infile, 'buffer'): |  | ||||||
|             infile = infile.buffer |  | ||||||
|         if hasattr(outfile, 'buffer'): |  | ||||||
|             outfile = outfile.buffer |  | ||||||
|         self.outfile, self.infile = outfile, infile |         self.outfile, self.infile = outfile, infile | ||||||
|         if sys.platform == "win32": |         if sys.platform == "win32": | ||||||
|             import msvcrt |             import msvcrt | ||||||
|  | @ -132,6 +128,9 @@ sys.stdin = tempfile.TemporaryFile('r') | ||||||
| 
 | 
 | ||||||
|     def read(self, numbytes): |     def read(self, numbytes): | ||||||
|         """Read exactly 'numbytes' bytes from the pipe. """ |         """Read exactly 'numbytes' bytes from the pipe. """ | ||||||
|  |         try: | ||||||
|  |             data = self.infile.buffer.read(numbytes) | ||||||
|  |         except AttributeError: | ||||||
|             data = self.infile.read(numbytes) |             data = self.infile.read(numbytes) | ||||||
|         if len(data) < numbytes: |         if len(data) < numbytes: | ||||||
|             raise EOFError |             raise EOFError | ||||||
|  | @ -140,6 +139,9 @@ sys.stdin = tempfile.TemporaryFile('r') | ||||||
|     def write(self, data): |     def write(self, data): | ||||||
|         """write out all data bytes. """  |         """write out all data bytes. """  | ||||||
|         assert isinstance(data, bytes) |         assert isinstance(data, bytes) | ||||||
|  |         try: | ||||||
|  |             self.outfile.buffer.write(data) | ||||||
|  |         except AttributeError: | ||||||
|             self.outfile.write(data) |             self.outfile.write(data) | ||||||
|         self.outfile.flush() |         self.outfile.flush() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,11 +22,17 @@ class XSpec: | ||||||
|                 key, value = keyvalue, True |                 key, value = keyvalue, True | ||||||
|             else: |             else: | ||||||
|                 key, value = keyvalue[:i], keyvalue[i+1:] |                 key, value = keyvalue[:i], keyvalue[i+1:] | ||||||
|             # XXX be restrictive for now |             if key[0] == "_": | ||||||
|             if key not in XSpec.__dict__: |  | ||||||
|                 raise AttributeError("%r not a valid XSpec key" % key) |                 raise AttributeError("%r not a valid XSpec key" % key) | ||||||
|  |             if key in self.__dict__: | ||||||
|  |                 raise ValueError("duplicate key: %r in %r" %(key, string)) | ||||||
|             setattr(self, key, value) |             setattr(self, key, value) | ||||||
| 
 | 
 | ||||||
|  |     def __getattr__(self, name): | ||||||
|  |         if name[0] == "_": | ||||||
|  |             raise AttributeError(name) | ||||||
|  |         return None | ||||||
|  | 
 | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return "<XSpec %r>" %(self._spec,) |         return "<XSpec %r>" %(self._spec,) | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|  | @ -39,11 +45,6 @@ class XSpec: | ||||||
|     def __ne__(self, other): |     def __ne__(self, other): | ||||||
|         return self._spec != getattr(other, '_spec', None) |         return self._spec != getattr(other, '_spec', None) | ||||||
| 
 | 
 | ||||||
|     #def __getattr__(self, name): |  | ||||||
|     #    if name[0] == "_": |  | ||||||
|     #        raise AttributeError(name)  |  | ||||||
|     #    return None |  | ||||||
| 
 |  | ||||||
|     def _samefilesystem(self): |     def _samefilesystem(self): | ||||||
|         return bool(self.popen and not self.chdir) |         return bool(self.popen and not self.chdir) | ||||||
| 
 | 
 | ||||||
|  | @ -58,6 +59,8 @@ def makegateway(spec): | ||||||
|         assert not spec.python, "socket: specifying python executables not supported" |         assert not spec.python, "socket: specifying python executables not supported" | ||||||
|         hostport = spec.socket.split(":") |         hostport = spec.socket.split(":") | ||||||
|         gw = py.execnet.SocketGateway(*hostport) |         gw = py.execnet.SocketGateway(*hostport) | ||||||
|  |     else: | ||||||
|  |         raise ValueError("no gateway type found for %r" % (spec._spec,)) | ||||||
|     gw.spec = spec  |     gw.spec = spec  | ||||||
|     if spec.chdir or spec.nice: |     if spec.chdir or spec.nice: | ||||||
|         channel = gw.remote_exec(""" |         channel = gw.remote_exec(""" | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ class TestXSpec: | ||||||
|         assert spec.python == "c:/this/python2.5"  |         assert spec.python == "c:/this/python2.5"  | ||||||
|         assert spec.chdir == "d:\hello" |         assert spec.chdir == "d:\hello" | ||||||
|         assert spec.nice is None |         assert spec.nice is None | ||||||
|         assert not hasattr(spec, 'xyz') |         assert not hasattr(spec, '_xyz') | ||||||
| 
 | 
 | ||||||
|         py.test.raises(AttributeError, "spec._hello") |         py.test.raises(AttributeError, "spec._hello") | ||||||
| 
 | 
 | ||||||
|  | @ -36,6 +36,14 @@ class TestXSpec: | ||||||
|         for x in ("popen", "popen//python=this"): |         for x in ("popen", "popen//python=this"): | ||||||
|             assert XSpec(x)._spec == x |             assert XSpec(x)._spec == x | ||||||
| 
 | 
 | ||||||
|  |     def test_samekeyword_twice_raises(self): | ||||||
|  |         py.test.raises(ValueError, "XSpec('popen//popen')") | ||||||
|  |         py.test.raises(ValueError, "XSpec('popen//popen=123')") | ||||||
|  | 
 | ||||||
|  |     def test_unknown_keys_allowed(self): | ||||||
|  |         xspec = XSpec("hello=3") | ||||||
|  |         assert xspec.hello == '3' | ||||||
|  | 
 | ||||||
|     def test_repr_and_string(self): |     def test_repr_and_string(self): | ||||||
|         for x in ("popen", "popen//python=this"): |         for x in ("popen", "popen//python=this"): | ||||||
|             assert repr(XSpec(x)).find("popen") != -1 |             assert repr(XSpec(x)).find("popen") != -1 | ||||||
|  | @ -48,6 +56,9 @@ class TestXSpec: | ||||||
|         assert hash(XSpec("socket=hello:8080")) != hash(XSpec("popen")) |         assert hash(XSpec("socket=hello:8080")) != hash(XSpec("popen")) | ||||||
| 
 | 
 | ||||||
| class TestMakegateway: | class TestMakegateway: | ||||||
|  |     def test_no_type(self): | ||||||
|  |         py.test.raises(ValueError, "py.execnet.makegateway('hello')") | ||||||
|  | 
 | ||||||
|     def test_popen(self): |     def test_popen(self): | ||||||
|         gw = py.execnet.makegateway("popen") |         gw = py.execnet.makegateway("popen") | ||||||
|         assert gw.spec.python == None |         assert gw.spec.python == None | ||||||
|  | @ -76,20 +87,20 @@ class TestMakegateway: | ||||||
|         assert rinfo.cwd == py.std.os.getcwd() |         assert rinfo.cwd == py.std.os.getcwd() | ||||||
|         assert rinfo.version_info == py.std.sys.version_info |         assert rinfo.version_info == py.std.sys.version_info | ||||||
| 
 | 
 | ||||||
|     def test_popen_cpython24(self): |     def test_popen_cpython25(self): | ||||||
|         for trypath in ('python2.4', r'C:\Python24\python.exe'): |         for trypath in ('python2.5', r'C:\Python25\python.exe'): | ||||||
|             cpython24 = py.path.local.sysfind(trypath) |             cpython25 = py.path.local.sysfind(trypath) | ||||||
|             if cpython24 is not None: |             if cpython25 is not None: | ||||||
|                 cpython24 = cpython24.realpath() |                 cpython25 = cpython25.realpath() | ||||||
|                 break |                 break | ||||||
|         else: |         else: | ||||||
|             py.test.skip("cpython2.4 not found") |             py.test.skip("cpython2.5 not found") | ||||||
|         gw = py.execnet.makegateway("popen//python=%s" % cpython24) |         gw = py.execnet.makegateway("popen//python=%s" % cpython25) | ||||||
|         rinfo = gw._rinfo() |         rinfo = gw._rinfo() | ||||||
|         if py.std.sys.platform != "darwin": # it's confusing there  |         if py.std.sys.platform != "darwin": # it's confusing there  | ||||||
|             assert rinfo.executable == cpython24   |             assert rinfo.executable == cpython25   | ||||||
|         assert rinfo.cwd == py.std.os.getcwd() |         assert rinfo.cwd == py.std.os.getcwd() | ||||||
|         assert rinfo.version_info[:2] == (2,4) |         assert rinfo.version_info[:2] == (2,5) | ||||||
| 
 | 
 | ||||||
|     def test_popen_cpython26(self): |     def test_popen_cpython26(self): | ||||||
|         for trypath in ('python2.6', r'C:\Python26\python.exe'): |         for trypath in ('python2.6', r'C:\Python26\python.exe'): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue