{"action":"created","comment":{"url":"https://api.github.com/repos/scopatz/xonsh/pulls/comments/27363557","id":27363557,"diff_hunk":"@@ -0,0 +1,80 @@\n+\"\"\"Import hooks for importing xonsh source files. This module registers\n+the hooks it defines when it is imported.\n+\"\"\"\n+from __future__ import print_function, unicode_literals\n+import os\n+import sys\n+import builtins\n+from importlib.machinery import ModuleSpec\n+from importlib.abc import MetaPathFinder, SourceLoader\n+\n+from xonsh.tools import string_types\n+from xonsh.execer import Execer\n+\n+class XonshImportHook(MetaPathFinder, SourceLoader):\n+    \"\"\"Implements the import hook for xonsh source files.\"\"\"\n+\n+    def __init__(self, *args, **kwargs):\n+        super(XonshImportHook, self).__init__(*args, **kwargs)\n+        self._filenames = {}\n+        self._execer = None\n+\n+    @property\n+    def execer(self):\n+        if hasattr(builtins, '__xonsh_execer__'):\n+            execer = builtins.__xonsh_execer__\n+            if self._execer is not None:\n+                self._execer = None\n+        elif self._execer is None:\n+            self._execer = execer = Execer(unload=False)\n+        else:\n+            execer = self._execer\n+        return execer\n+    #\n+    # MetaPathFinder methods\n+    #\n+    def find_spec(self, fullname, path, target=None):\n+        \"\"\"Finds the spec for a xonsh module if it exists.\"\"\"\n+        spec = None\n+        path = sys.path if path is None else path\n+        name = fullname.rsplit('.', 1)[-1]\n+        fname = name + '.xsh'\n+        for p in path:\n+            if not isinstance(p, string_types):\n+                continue\n+            if not os.path.isdir(p):\n+                continue\n+            if fname not in os.listdir(p):\n+                continue\n+            spec = ModuleSpec(fullname, self)\n+            self._filenames[fullname] = os.path.join(p, fname)\n+            break\n+        return spec\n+\n+    #\n+    # SourceLoader methods\n+    #\n+    def get_filename(self, fullname):\n+        \"\"\"Returns the filename for a module's fullname.\"\"\"\n+        return self._filenames[fullname]\n+\n+    def get_data(self, path):\n+        \"\"\"Gets the bytes for a path.\"\"\"\n+        raise NotImplementedError\n+\n+    def get_code(self, fullname):\n+        \"\"\"Gets the code object for a xonsh file.\"\"\"\n+        filename = self._filenames.get(fullname, None)\n+        if filename is None:\n+            msg = \"xonsh file {0!r} could not be found\".format(fullname)\n+            raise ImportError(msg)\n+        with open(filename, 'r') as f:\n+            src = f.read()\n+        src = src if src.endswith('\\n') else src + '\\n'\n+        execer = self.execer\n+        execer.filename = filename\n+        ctx = {}   # dummy for modules\n+        code = execer.compile(src, glbs=ctx, locs=ctx)\n+        return code\n+ ","path":"xonsh/imphooks.py","position":79,"original_position":79,"commit_id":"88a48f844a10cb0a8859b24e5b1b24f0926cbd16","original_commit_id":"88a48f844a10cb0a8859b24e5b1b24f0926cbd16","user":{"login":"wrywerytwreywery","id":549404,"avatar_url":"https://avatars.githubusercontent.com/u/549404?v=3","gravatar_id":"","url":"https://api.github.com/users/wrywerytwreywery","html_url":"https://github.com/wrywerytwreywery","followers_url":"https://api.github.com/users/wrywerytwreywery/followers","following_url":"https://api.github.com/users/wrywerytwreywery/following{/other_user}","gists_url":"https://api.github.com/users/wrywerytwreywery/gists{/gist_id}","starred_url":"https://api.github.com/users/wrywerytwreywery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wrywerytwreywery/subscriptions","organizations_url":"https://api.github.com/users/wrywerytwreywery/orgs","repos_url":"https://api.github.com/users/wrywerytwreywery/repos","events_url":"https://api.github.com/users/wrywerytwreywery/events{/privacy}","received_events_url":"https://api.github.com/users/wrywerytwreywery/received_events","type":"User","site_admin":false},"body":"PEP8: Whitespace in this line","created_at":"2015-03-30T02:18:49Z","updated_at":"2015-03-30T02:18:49Z","html_url":"https://github.com/scopatz/xonsh/pull/164#discussion_r27363557","pull_request_url":"https://api.github.com/repos/scopatz/xonsh/pulls/164","_links":{"self":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/comments/27363557"},"html":{"href":"https://github.com/scopatz/xonsh/pull/164#discussion_r27363557"},"pull_request":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/164"}}},"pull_request":{"url":"https://api.github.com/repos/scopatz/xonsh/pulls/164","id":32190709,"html_url":"https://github.com/scopatz/xonsh/pull/164","diff_url":"https://github.com/scopatz/xonsh/pull/164.diff","patch_url":"https://github.com/scopatz/xonsh/pull/164.patch","issue_url":"https://api.github.com/repos/scopatz/xonsh/issues/164","number":164,"state":"open","locked":false,"title":"Import hooks for xonsh files (*.xsh)","user":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"body":"This PR adds the capability for xonsh source files (*.xsh) to be imported using Python's normal import mechanisms, which is frankly pretty great.  In addition to being able to write xonsh scripts, libraries, and packages, it also gives us a way to source (in the bash sense) a xonsh file via:\r\n\r\n```python\r\nfrom myxonsh import *\r\n```\r\n\r\nI am not enamoured with the file *.xsh file extension, but this is what the mailing list sort of agreed to.  We can always change it later.  (My personal fav was *.xo).  It'd be nice to have this is v0.1.4 if you are available to review it tonight @wrywerytwreywery.","created_at":"2015-03-29T23:38:27Z","updated_at":"2015-03-30T02:18:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d027b8e07c3b3a25d1c17ed46e022a80ce518aab","assignee":null,"milestone":{"url":"https://api.github.com/repos/scopatz/xonsh/milestones/1","html_url":"https://github.com/scopatz/xonsh/milestones/v0.2","labels_url":"https://api.github.com/repos/scopatz/xonsh/milestones/1/labels","id":1013181,"number":1,"title":"v0.2","description":"","creator":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"open_issues":36,"closed_issues":124,"state":"open","created_at":"2015-03-09T18:29:10Z","updated_at":"2015-03-30T01:46:26Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/scopatz/xonsh/pulls/164/commits","review_comments_url":"https://api.github.com/repos/scopatz/xonsh/pulls/164/comments","review_comment_url":"https://api.github.com/repos/scopatz/xonsh/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scopatz/xonsh/issues/164/comments","statuses_url":"https://api.github.com/repos/scopatz/xonsh/statuses/88a48f844a10cb0a8859b24e5b1b24f0926cbd16","head":{"label":"scopatz:imp","ref":"imp","sha":"88a48f844a10cb0a8859b24e5b1b24f0926cbd16","user":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"repo":{"id":29620400,"name":"xonsh","full_name":"scopatz/xonsh","owner":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/scopatz/xonsh","description":"xonsh is a Python-ish, BASHwards-compatible shell.","fork":false,"url":"https://api.github.com/repos/scopatz/xonsh","forks_url":"https://api.github.com/repos/scopatz/xonsh/forks","keys_url":"https://api.github.com/repos/scopatz/xonsh/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scopatz/xonsh/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scopatz/xonsh/teams","hooks_url":"https://api.github.com/repos/scopatz/xonsh/hooks","issue_events_url":"https://api.github.com/repos/scopatz/xonsh/issues/events{/number}","events_url":"https://api.github.com/repos/scopatz/xonsh/events","assignees_url":"https://api.github.com/repos/scopatz/xonsh/assignees{/user}","branches_url":"https://api.github.com/repos/scopatz/xonsh/branches{/branch}","tags_url":"https://api.github.com/repos/scopatz/xonsh/tags","blobs_url":"https://api.github.com/repos/scopatz/xonsh/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scopatz/xonsh/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scopatz/xonsh/git/refs{/sha}","trees_url":"https://api.github.com/repos/scopatz/xonsh/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scopatz/xonsh/statuses/{sha}","languages_url":"https://api.github.com/repos/scopatz/xonsh/languages","stargazers_url":"https://api.github.com/repos/scopatz/xonsh/stargazers","contributors_url":"https://api.github.com/repos/scopatz/xonsh/contributors","subscribers_url":"https://api.github.com/repos/scopatz/xonsh/subscribers","subscription_url":"https://api.github.com/repos/scopatz/xonsh/subscription","commits_url":"https://api.github.com/repos/scopatz/xonsh/commits{/sha}","git_commits_url":"https://api.github.com/repos/scopatz/xonsh/git/commits{/sha}","comments_url":"https://api.github.com/repos/scopatz/xonsh/comments{/number}","issue_comment_url":"https://api.github.com/repos/scopatz/xonsh/issues/comments{/number}","contents_url":"https://api.github.com/repos/scopatz/xonsh/contents/{+path}","compare_url":"https://api.github.com/repos/scopatz/xonsh/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scopatz/xonsh/merges","archive_url":"https://api.github.com/repos/scopatz/xonsh/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scopatz/xonsh/downloads","issues_url":"https://api.github.com/repos/scopatz/xonsh/issues{/number}","pulls_url":"https://api.github.com/repos/scopatz/xonsh/pulls{/number}","milestones_url":"https://api.github.com/repos/scopatz/xonsh/milestones{/number}","notifications_url":"https://api.github.com/repos/scopatz/xonsh/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scopatz/xonsh/labels{/name}","releases_url":"https://api.github.com/repos/scopatz/xonsh/releases{/id}","created_at":"2015-01-21T22:05:27Z","updated_at":"2015-03-29T20:42:52Z","pushed_at":"2015-03-30T01:45:13Z","git_url":"git://github.com/scopatz/xonsh.git","ssh_url":"git@github.com:scopatz/xonsh.git","clone_url":"https://github.com/scopatz/xonsh.git","svn_url":"https://github.com/scopatz/xonsh","homepage":"http://xonsh.org","size":3915,"stargazers_count":335,"watchers_count":335,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":30,"mirror_url":null,"open_issues_count":38,"forks":30,"open_issues":38,"watchers":335,"default_branch":"master"}},"base":{"label":"scopatz:master","ref":"master","sha":"1ff8b24cdf070125a36818ada55b052ac244ec59","user":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"repo":{"id":29620400,"name":"xonsh","full_name":"scopatz/xonsh","owner":{"login":"scopatz","id":320553,"avatar_url":"https://avatars.githubusercontent.com/u/320553?v=3","gravatar_id":"","url":"https://api.github.com/users/scopatz","html_url":"https://github.com/scopatz","followers_url":"https://api.github.com/users/scopatz/followers","following_url":"https://api.github.com/users/scopatz/following{/other_user}","gists_url":"https://api.github.com/users/scopatz/gists{/gist_id}","starred_url":"https://api.github.com/users/scopatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scopatz/subscriptions","organizations_url":"https://api.github.com/users/scopatz/orgs","repos_url":"https://api.github.com/users/scopatz/repos","events_url":"https://api.github.com/users/scopatz/events{/privacy}","received_events_url":"https://api.github.com/users/scopatz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/scopatz/xonsh","description":"xonsh is a Python-ish, BASHwards-compatible shell.","fork":false,"url":"https://api.github.com/repos/scopatz/xonsh","forks_url":"https://api.github.com/repos/scopatz/xonsh/forks","keys_url":"https://api.github.com/repos/scopatz/xonsh/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scopatz/xonsh/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scopatz/xonsh/teams","hooks_url":"https://api.github.com/repos/scopatz/xonsh/hooks","issue_events_url":"https://api.github.com/repos/scopatz/xonsh/issues/events{/number}","events_url":"https://api.github.com/repos/scopatz/xonsh/events","assignees_url":"https://api.github.com/repos/scopatz/xonsh/assignees{/user}","branches_url":"https://api.github.com/repos/scopatz/xonsh/branches{/branch}","tags_url":"https://api.github.com/repos/scopatz/xonsh/tags","blobs_url":"https://api.github.com/repos/scopatz/xonsh/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scopatz/xonsh/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scopatz/xonsh/git/refs{/sha}","trees_url":"https://api.github.com/repos/scopatz/xonsh/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scopatz/xonsh/statuses/{sha}","languages_url":"https://api.github.com/repos/scopatz/xonsh/languages","stargazers_url":"https://api.github.com/repos/scopatz/xonsh/stargazers","contributors_url":"https://api.github.com/repos/scopatz/xonsh/contributors","subscribers_url":"https://api.github.com/repos/scopatz/xonsh/subscribers","subscription_url":"https://api.github.com/repos/scopatz/xonsh/subscription","commits_url":"https://api.github.com/repos/scopatz/xonsh/commits{/sha}","git_commits_url":"https://api.github.com/repos/scopatz/xonsh/git/commits{/sha}","comments_url":"https://api.github.com/repos/scopatz/xonsh/comments{/number}","issue_comment_url":"https://api.github.com/repos/scopatz/xonsh/issues/comments{/number}","contents_url":"https://api.github.com/repos/scopatz/xonsh/contents/{+path}","compare_url":"https://api.github.com/repos/scopatz/xonsh/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scopatz/xonsh/merges","archive_url":"https://api.github.com/repos/scopatz/xonsh/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scopatz/xonsh/downloads","issues_url":"https://api.github.com/repos/scopatz/xonsh/issues{/number}","pulls_url":"https://api.github.com/repos/scopatz/xonsh/pulls{/number}","milestones_url":"https://api.github.com/repos/scopatz/xonsh/milestones{/number}","notifications_url":"https://api.github.com/repos/scopatz/xonsh/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scopatz/xonsh/labels{/name}","releases_url":"https://api.github.com/repos/scopatz/xonsh/releases{/id}","created_at":"2015-01-21T22:05:27Z","updated_at":"2015-03-29T20:42:52Z","pushed_at":"2015-03-30T01:45:13Z","git_url":"git://github.com/scopatz/xonsh.git","ssh_url":"git@github.com:scopatz/xonsh.git","clone_url":"https://github.com/scopatz/xonsh.git","svn_url":"https://github.com/scopatz/xonsh","homepage":"http://xonsh.org","size":3915,"stargazers_count":335,"watchers_count":335,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":30,"mirror_url":null,"open_issues_count":38,"forks":30,"open_issues":38,"watchers":335,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/164"},"html":{"href":"https://github.com/scopatz/xonsh/pull/164"},"issue":{"href":"https://api.github.com/repos/scopatz/xonsh/issues/164"},"comments":{"href":"https://api.github.com/repos/scopatz/xonsh/issues/164/comments"},"review_comments":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/164/comments"},"review_comment":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scopatz/xonsh/pulls/164/commits"},"statuses":{"href":"https://api.github.com/repos/scopatz/xonsh/statuses/88a48f844a10cb0a8859b24e5b1b24f0926cbd16"}}}}