Repository: ethereum/web3.py

Issue:
Windows IPC/Named pipe does not work
Right now web3.py use sockets on GNU/Linux to connect to the IPC. This wont work on Windows since named pipes on windows does not make use of sockets. From what google says you can use a simple file handle to write and read on the named pipe (\.\pipe\geth.ipc). I have tried using simple popen/open to read and write data, but no luck. 

I have also tried to use this library for python, http://docs.activestate.com/activepython/2.6/pywin32/win32file.html

Next step is to check how the JS-version of web3 is connecting to the named pipe, but i can imagine that it uses a more low level connection directly via ethereum code base.



Discussion:
Thank you for investigating this. I don't use Windows myself and therefore can't test it. If you find a solution, feel free to submit a pull request.


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 import os
+import sys
 
 from setuptools import (
     setup,
@@ -13,6 +14,17 @@
 
 readme = open(os.path.join(DIR, 'README.md')).read()
 
+install_requires=[
+    "ethereum-abi-utils>=0.4.0",
+    "ethereum-utils>=0.2.0",
+    "pylru>=1.0.9",
+    "pysha3>=0.3",
+    "requests>=2.12.4",
+    "rlp>=0.4.6,<0.4.7",
+]
+
+if sys.platform == 'win32':
+    install_requires.append('pypiwin32')
 
 setup(
     name='web3',
@@ -23,14 +35,7 @@
     author_email='pipermerriam@gmail.com',
     url='https://github.com/pipermerriam/web3.py',
     include_package_data=True,
-    install_requires=[
-        "ethereum-abi-utils>=0.4.0",
-        "ethereum-utils>=0.2.0",
-        "pylru>=1.0.9",
-        "pysha3>=0.3",
-        "requests>=2.12.4",
-        "rlp>=0.4.6,<0.4.7",
-    ],
+    install_requires=install_requires,
     extras_require={
         'Tester': ["eth-testrpc>=1.1.0"],
         'tester': ["eth-testrpc>=1.1.0"],
diff --git a/web3/providers/ipc.py b/web3/providers/ipc.py
--- a/web3/providers/ipc.py
+++ b/web3/providers/ipc.py
@@ -25,13 +25,19 @@
 
 @contextlib.contextmanager
 def get_ipc_socket(ipc_path, timeout=0.1):
-    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    sock.connect(ipc_path)
-    sock.settimeout(timeout)
+    if sys.platform == 'win32':
+        # On Windows named pipe is used. Simulate socket with it.
+        from web3.utils.windows import NamedPipe
 
-    yield sock
-
-    sock.close()
+        pipe = NamedPipe(ipc_path)
+        with contextlib.closing(pipe):
+            yield pipe
+    else:
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        sock.connect(ipc_path)
+        sock.settimeout(timeout)
+        with contextlib.closing(sock):
+            yield sock
 
 
 def get_default_ipc_path(testnet=False):
@@ -56,12 +62,7 @@ def get_default_ipc_path(testnet=False):
             "geth.ipc",
         ))
     elif sys.platform == 'win32':
-        return os.path.expanduser(os.path.join(
-            "~",
-            "AppData",
-            "Roaming",
-            "Ethereum",
-        ))
+        return "\\\\.\\pipe\\geth.ipc"
     else:
         raise ValueError(
             "Unsupported platform '{0}'.  Only darwin/linux2/win32 are "
diff --git a/web3/utils/windows.py b/web3/utils/windows.py
new file mode 100644
--- /dev/null
+++ b/web3/utils/windows.py
@@ -0,0 +1,31 @@
+import sys
+
+
+if sys.platform != 'win32':
+    raise ImportError("This module should not be imported on non `win32` platforms")
+
+
+import win32file  # noqa: E402
+import pywintypes  # noqa: E402
+
+
+class NamedPipe(object):
+    def __init__(self, ipc_path):
+        try:
+            self.handle = win32file.CreateFile(
+                ipc_path, win32file.GENERIC_READ | win32file.GENERIC_WRITE,
+                0, None, win32file.OPEN_EXISTING, 0, None)
+        except pywintypes.error as err:
+            raise IOError(err)
+
+    def recv(self, max_length):
+        (err, data) = win32file.ReadFile(self.handle, max_length)
+        if err:
+            raise IOError(err)
+        return data
+
+    def sendall(self, data):
+        return win32file.WriteFile(self.handle, data)
+
+    def close(self):
+        self.handle.close()


Test patch: