{"action":"created","issue":{"url":"https://api.github.com/repos/jaraco/keyring/issues/78","labels_url":"https://api.github.com/repos/jaraco/keyring/issues/78/labels{/name}","comments_url":"https://api.github.com/repos/jaraco/keyring/issues/78/comments","events_url":"https://api.github.com/repos/jaraco/keyring/issues/78/events","html_url":"https://github.com/jaraco/keyring/issues/78","id":58744201,"number":78,"title":"Pyfilesystem backend fails on Windows","user":{"login":"jaraco","id":308610,"avatar_url":"https://avatars.githubusercontent.com/u/308610?v=3","gravatar_id":"","url":"https://api.github.com/users/jaraco","html_url":"https://github.com/jaraco","followers_url":"https://api.github.com/users/jaraco/followers","following_url":"https://api.github.com/users/jaraco/following{/other_user}","gists_url":"https://api.github.com/users/jaraco/gists{/gist_id}","starred_url":"https://api.github.com/users/jaraco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaraco/subscriptions","organizations_url":"https://api.github.com/users/jaraco/orgs","repos_url":"https://api.github.com/users/jaraco/repos","events_url":"https://api.github.com/users/jaraco/events{/privacy}","received_events_url":"https://api.github.com/users/jaraco/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-02-24T14:19:25Z","updated_at":"2015-02-24T14:19:30Z","closed_at":"2015-02-24T14:19:25Z","body":"I got around to installing pyfilesystem on Windows, and found all of the tests fail with an error similar to this:\n\n```\n___ UnencryptedLocalPyfilesystemKeyringSubDirTestCase.test_password_set_get ___\n\nself = <keyring.tests.backends.test_pyfs.UnencryptedLocalPyfilesystemKeyringSubDirTestCase testMethod=test_password_set_get>\n\n    def test_password_set_get(self):\n        password = random_string(20)\n        username = random_string(20)\n        service = random_string(20)\n>       self.check_set_get(service, username, password)\n\nkeyring\\tests\\test_backend.py:163:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <keyring.tests.backends.test_pyfs.UnencryptedLocalPyfilesystemKeyringSubDirTestCase testMethod=test_password_set_get>\nservice = 'WOYLQVJuWIc8QZZ4NulD', username = '4uBR6xyoevdbbS18DhND'\npassword = 'uBZ87uGqiF8UEec6PS5i'\n\n    def check_set_get(self, service, username, password):\n        keyring = self.keyring\n\n        # for the non-existent password\n>       self.assertEqual(keyring.get_password(service, username), None)\n\nkeyring\\tests\\test_backend.py:149:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <keyring.backends.pyfs.PlaintextKeyring object at 0x0000000003C78128>\nservice = 'WOYLQVJuWIc8QZZ4NulD', username = '4uBR6xyoevdbbS18DhND'\n\n    def get_password(self, service, username):\n        \"\"\"Read the password from the file.\n            \"\"\"\n        service = escape_for_ini(service)\n        username = escape_for_ini(username)\n\n        # fetch the password\n        try:\n>           password_base64 = self.config.get(service, username).encode()\n\nkeyring\\backends\\pyfs.py:160:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <keyring.backends.pyfs.PlaintextKeyring object at 0x0000000003C78128>\n\n    @property\n    def config(self):\n        \"\"\"load the passwords from the config file\n            \"\"\"\n        if not hasattr(self, '_config'):\n            raw_config = configparser.RawConfigParser()\n>           f = self._open()\n\nkeyring\\backends\\pyfs.py:145:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <keyring.backends.pyfs.PlaintextKeyring object at 0x0000000003C78128>\nmode = 'rb'\n\n    def _open(self, mode='rb'):\n        \"\"\"Open the password file in the specified mode\n            \"\"\"\n        import fs.opener\n        import fs.errors\n        import fs.path\n        import fs.remote\n        open_file = None\n        writeable = 'w' in mode or 'a' in mode or '+' in mode\n        try:\n            # NOTE: currently the MemOpener does not split off any filename\n            #       which causes errors on close()\n            #       so we add a dummy name and open it separately\n            if (self.filename.startswith('mem://') or\n                self.filename.startswith('ram://')):\n                open_file = fs.opener.fsopendir(self.filename).open('kr.cfg',\n                                                                    mode)\n            else:\n                if not hasattr(self, '_pyfs'):\n                    # reuse the pyfilesystem and path\n                    self._pyfs, self._path = fs.opener.opener.parse(self.filename,\n                                               writeable=writeable)\n                    # cache if permitted\n                    if self._cache_timeout is not None:\n                        self._pyfs = fs.remote.CacheFS(\n                            self._pyfs, cache_timeout=self._cache_timeout)\n                open_file = self._pyfs.open(self._path, mode)\n        except fs.errors.ResourceNotFoundError:\n            if self._can_create:\n                segments = fs.opener.opener.split_segments(self.filename)\n                if segments:\n                    # this seems broken, but pyfilesystem uses it, so we must\n                    fs_name, credentials, url1, url2, path = segments.groups()\n                    assert fs_name, 'Should be a remote filesystem'\n                    host = ''\n                    # allow for domain:port\n                    if ':' in url2:\n                        split_url2 = url2.split('/', 1)\n                        if len(split_url2) > 1:\n                            url2 = split_url2[1]\n                        else:\n                            url2 = ''\n                        host = split_url2[0]\n                    pyfs = fs.opener.opener.opendir('%s://%s' %(fs_name, host))\n                    # cache if permitted\n                    if self._cache_timeout is not None:\n                        pyfs = fs.remote.CacheFS(\n                            pyfs, cache_timeout=self._cache_timeout)\n                    url2_path, url2_filename = fs.path.split(url2)\n                    if url2_path and not pyfs.exists(url2_path):\n                        pyfs.makedir(url2_path, recursive=True)\n                else:\n                    # assume local filesystem\n                    import fs.osfs\n                    full_url = fs.opener._expand_syspath(self.filename)\n                    url2_path, url2 = fs.path.split(full_url)\n                    pyfs = fs.osfs.OSFS(url2_path)\n\n                try:\n                    # reuse the pyfilesystem and path\n                    self._pyfs = pyfs\n                    self._path = url2\n>                   return pyfs.open(url2, mode)\n\nkeyring\\backends\\pyfs.py:126:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <fs.osfs.OSFS object at 0x0000000003C78A58>\nargs = ('c:\\\\users\\\\jaraco\\\\appdata\\\\local\\\\temp\\\\tmpi7ggom\\\\more\\\\sub\\\\dirs\\\\keyring.cfg', 'rb')\nkwds = {}\n\n    @wraps(func)\n    def wrapper(self,*args,**kwds):\n        try:\n>           return func(self,*args,**kwds)\n\nfs-0.4.0-py2.7.egg\\fs\\errors.py:229:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <fs.osfs.OSFS object at 0x0000000003C78A58>\npath = 'c:\\\\users\\\\jaraco\\\\appdata\\\\local\\\\temp\\\\tmpi7ggom\\\\more\\\\sub\\\\dirs\\\\keyring.cfg'\nmode = 'rb', kwargs = {}\n\n    @convert_os_errors\n    def open(self, path, mode=\"r\", **kwargs):\n        mode = filter(lambda c: c in \"rwabt+\",mode)\n>       sys_path = self.getsyspath(path)\n\nfs-0.4.0-py2.7.egg\\fs\\osfs\\__init__.py:209:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = <fs.osfs.OSFS object at 0x0000000003C78A58>\npath = 'c:\\\\users\\\\jaraco\\\\appdata\\\\local\\\\temp\\\\tmpi7ggom\\\\more\\\\sub\\\\dirs\\\\keyring.cfg'\nallow_none = False\n\n    def getsyspath(self, path, allow_none=False):\n        path = relpath(normpath(path)).replace(\"/\",os.sep)\n        path = os.path.join(self.root_path, path)\n        if not path.startswith(self.root_path):\n>           raise PathError(path,msg=\"OSFS given path outside root: %(path)s\")\nE           PathError: OSFS given path outside root: c:\\users\\jaraco\\appdata\\local\\temp\\tmpi7ggom\\more\\sub\\dirs\\keyring.cfg\n\nfs-0.4.0-py2.7.egg\\fs\\osfs\\__init__.py:149: PathError\n```\n\nNote that at that point, self.root_path is r'\\\\?\\c:\\users\\jaraco\\appdata\\local\\temp\\tmpi7ggom' or similar.\n\nWhen I encountered the error, it looked like a bug if Pyfilesystem, so I [filed a bug upstream](http://code.google.com/p/pyfilesystem/issues/detail?id=143) but their response indicates that it's the keyring usage that's incorrect, not a bug in OSFS.\n\n----------------------------------------\n- Bitbucket: https://bitbucket.org/kang/python-keyring-lib/issue/78\n- Originally reported by: Jason R. Coombs\n- Originally created at: 2012-12-30T17:50:49.438\n"},"comment":{"url":"https://api.github.com/repos/jaraco/keyring/issues/comments/75763822","html_url":"https://github.com/jaraco/keyring/issues/78#issuecomment-75763822","issue_url":"https://api.github.com/repos/jaraco/keyring/issues/78","id":75763822,"user":{"login":"jaraco","id":308610,"avatar_url":"https://avatars.githubusercontent.com/u/308610?v=3","gravatar_id":"","url":"https://api.github.com/users/jaraco","html_url":"https://github.com/jaraco","followers_url":"https://api.github.com/users/jaraco/followers","following_url":"https://api.github.com/users/jaraco/following{/other_user}","gists_url":"https://api.github.com/users/jaraco/gists{/gist_id}","starred_url":"https://api.github.com/users/jaraco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaraco/subscriptions","organizations_url":"https://api.github.com/users/jaraco/orgs","repos_url":"https://api.github.com/users/jaraco/repos","events_url":"https://api.github.com/users/jaraco/events{/privacy}","received_events_url":"https://api.github.com/users/jaraco/received_events","type":"User","site_admin":false},"created_at":"2015-02-24T14:19:29Z","updated_at":"2015-02-24T14:19:29Z","body":"issue_78 branch fixes this. \n\nThe problem is that fs.path.split() does not work the same way as os.path.split() under windows and it was attempting to open the pyfilesystem at the root of the filesystem.\n\n----------------------------------------\nOriginal comment by: Robert Leftwich\n"}}