{"action":"created","comment":{"url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/comments/28642708","id":28642708,"diff_hunk":"@@ -0,0 +1,142 @@\n+\"\"\"Very low-level nginx config parser based on pyparsing.\"\"\"\n+import string\n+\n+from pyparsing import (\n+    Literal, White, Word, alphanums, CharsNotIn, Forward, Group,\n+    Optional, OneOrMore, ZeroOrMore, pythonStyleComment)\n+\n+\n+class RawNginxParser(object):\n+    # pylint: disable=expression-not-assigned\n+    \"\"\"\n+    A class that parses nginx configuration with pyparsing\n+    \"\"\"\n+\n+    # constants\n+    left_bracket = Literal(\"{\").suppress()\n+    right_bracket = Literal(\"}\").suppress()\n+    semicolon = Literal(\";\").suppress()\n+    space = White().suppress()\n+    key = Word(alphanums + \"_/\")\n+    value = CharsNotIn(\"{};,\")\n+    location = CharsNotIn(\"{};,\" + string.whitespace)\n+    # modifier for location uri [ = | ~ | ~* | ^~ ]\n+    modifier = Literal(\"=\") | Literal(\"~*\") | Literal(\"~\") | Literal(\"^~\")\n+\n+    # rules\n+    assignment = (key + Optional(space + value) + semicolon)\n+    block = Forward()\n+\n+    block << Group(\n+        Group(key + Optional(space + modifier) + Optional(space + location))\n+        + left_bracket\n+        + Group(ZeroOrMore(Group(assignment) | block))\n+        + right_bracket)\n+\n+    script = OneOrMore(Group(assignment) | block).ignore(pythonStyleComment)\n+\n+    def __init__(self, source):\n+        self.source = source\n+\n+    def parse(self):\n+        \"\"\"\n+        Returns the parsed tree.\n+        \"\"\"\n+        return self.script.parseString(self.source)\n+\n+    def as_list(self):\n+        \"\"\"\n+        Returns the list of tree.\n+        \"\"\"\n+        return self.parse().asList()\n+\n+\n+class RawNginxDumper(object):\n+    # pylint: disable=too-few-public-methods\n+    \"\"\"\n+    A class that dumps nginx configuration from the provided tree.\n+    \"\"\"","path":"letsencrypt/client/plugins/nginx/nginxparser.py","position":58,"original_position":58,"commit_id":"636f5aa313a617c296251886eb3d58bf4dc32657","original_commit_id":"636f5aa313a617c296251886eb3d58bf4dc32657","user":{"login":"kuba","id":106176,"avatar_url":"https://avatars.githubusercontent.com/u/106176?v=3","gravatar_id":"","url":"https://api.github.com/users/kuba","html_url":"https://github.com/kuba","followers_url":"https://api.github.com/users/kuba/followers","following_url":"https://api.github.com/users/kuba/following{/other_user}","gists_url":"https://api.github.com/users/kuba/gists{/gist_id}","starred_url":"https://api.github.com/users/kuba/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kuba/subscriptions","organizations_url":"https://api.github.com/users/kuba/orgs","repos_url":"https://api.github.com/users/kuba/repos","events_url":"https://api.github.com/users/kuba/events{/privacy}","received_events_url":"https://api.github.com/users/kuba/received_events","type":"User","site_admin":false},"body":"`\"\"\"A class that dumps nginx configuration from the provided tree.\"\"\"`","created_at":"2015-04-18T09:37:06Z","updated_at":"2015-04-18T09:37:06Z","html_url":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351#discussion_r28642708","pull_request_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351","_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/comments/28642708"},"html":{"href":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351#discussion_r28642708"},"pull_request":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351"}}},"pull_request":{"url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351","id":33500907,"html_url":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351","diff_url":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351.diff","patch_url":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351.patch","issue_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/351","number":351,"state":"open","locked":false,"title":"Start Nginx configurator","user":{"login":"diracdeltas","id":549654,"avatar_url":"https://avatars.githubusercontent.com/u/549654?v=3","gravatar_id":"","url":"https://api.github.com/users/diracdeltas","html_url":"https://github.com/diracdeltas","followers_url":"https://api.github.com/users/diracdeltas/followers","following_url":"https://api.github.com/users/diracdeltas/following{/other_user}","gists_url":"https://api.github.com/users/diracdeltas/gists{/gist_id}","starred_url":"https://api.github.com/users/diracdeltas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diracdeltas/subscriptions","organizations_url":"https://api.github.com/users/diracdeltas/orgs","repos_url":"https://api.github.com/users/diracdeltas/repos","events_url":"https://api.github.com/users/diracdeltas/events{/privacy}","received_events_url":"https://api.github.com/users/diracdeltas/received_events","type":"User","site_admin":false},"body":"Adds a plugin that implements the Authenticator and Installer interfaces on Nginx. This is not quite done yet (still need to implement DVSNI validation, config enhancements, and enable disabled sites) but should be okay to merge as it shouldn't interfere with the rest of the code.","created_at":"2015-04-16T22:58:11Z","updated_at":"2015-04-18T09:37:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c28d96ed8b59fc06f8c966dc4e233229d224bc3d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351/commits","review_comments_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351/comments","review_comment_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/comments{/number}","comments_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/351/comments","statuses_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/statuses/636f5aa313a617c296251886eb3d58bf4dc32657","head":{"label":"diracdeltas:feature/nginx","ref":"feature/nginx","sha":"636f5aa313a617c296251886eb3d58bf4dc32657","user":{"login":"diracdeltas","id":549654,"avatar_url":"https://avatars.githubusercontent.com/u/549654?v=3","gravatar_id":"","url":"https://api.github.com/users/diracdeltas","html_url":"https://github.com/diracdeltas","followers_url":"https://api.github.com/users/diracdeltas/followers","following_url":"https://api.github.com/users/diracdeltas/following{/other_user}","gists_url":"https://api.github.com/users/diracdeltas/gists{/gist_id}","starred_url":"https://api.github.com/users/diracdeltas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diracdeltas/subscriptions","organizations_url":"https://api.github.com/users/diracdeltas/orgs","repos_url":"https://api.github.com/users/diracdeltas/repos","events_url":"https://api.github.com/users/diracdeltas/events{/privacy}","received_events_url":"https://api.github.com/users/diracdeltas/received_events","type":"User","site_admin":false},"repo":{"id":32597328,"name":"lets-encrypt-preview","full_name":"diracdeltas/lets-encrypt-preview","owner":{"login":"diracdeltas","id":549654,"avatar_url":"https://avatars.githubusercontent.com/u/549654?v=3","gravatar_id":"","url":"https://api.github.com/users/diracdeltas","html_url":"https://github.com/diracdeltas","followers_url":"https://api.github.com/users/diracdeltas/followers","following_url":"https://api.github.com/users/diracdeltas/following{/other_user}","gists_url":"https://api.github.com/users/diracdeltas/gists{/gist_id}","starred_url":"https://api.github.com/users/diracdeltas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diracdeltas/subscriptions","organizations_url":"https://api.github.com/users/diracdeltas/orgs","repos_url":"https://api.github.com/users/diracdeltas/repos","events_url":"https://api.github.com/users/diracdeltas/events{/privacy}","received_events_url":"https://api.github.com/users/diracdeltas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/diracdeltas/lets-encrypt-preview","description":"An ACME client that can update Apache configurations (developer preview) ","fork":true,"url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview","forks_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/forks","keys_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/keys{/key_id}","collaborators_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/teams","hooks_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/hooks","issue_events_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/issues/events{/number}","events_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/events","assignees_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/assignees{/user}","branches_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/branches{/branch}","tags_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/tags","blobs_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/git/refs{/sha}","trees_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/git/trees{/sha}","statuses_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/statuses/{sha}","languages_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/languages","stargazers_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/stargazers","contributors_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/contributors","subscribers_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/subscribers","subscription_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/subscription","commits_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/commits{/sha}","git_commits_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/git/commits{/sha}","comments_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/comments{/number}","issue_comment_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/issues/comments{/number}","contents_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/contents/{+path}","compare_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/compare/{base}...{head}","merges_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/merges","archive_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/downloads","issues_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/issues{/number}","pulls_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/pulls{/number}","milestones_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/milestones{/number}","notifications_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/labels{/name}","releases_url":"https://api.github.com/repos/diracdeltas/lets-encrypt-preview/releases{/id}","created_at":"2015-03-20T17:25:26Z","updated_at":"2015-04-16T23:23:05Z","pushed_at":"2015-04-18T06:44:35Z","git_url":"git://github.com/diracdeltas/lets-encrypt-preview.git","ssh_url":"git@github.com:diracdeltas/lets-encrypt-preview.git","clone_url":"https://github.com/diracdeltas/lets-encrypt-preview.git","svn_url":"https://github.com/diracdeltas/lets-encrypt-preview","homepage":null,"size":2595,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"letsencrypt:master","ref":"master","sha":"55188c52e85d7e5cb9ece1f17a1289986af6d6fe","user":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"repo":{"id":26516210,"name":"lets-encrypt-preview","full_name":"letsencrypt/lets-encrypt-preview","owner":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/letsencrypt/lets-encrypt-preview","description":"An ACME client that can update Apache configurations (developer preview) ","fork":false,"url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview","forks_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/forks","keys_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/keys{/key_id}","collaborators_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/teams","hooks_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/hooks","issue_events_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/events{/number}","events_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/events","assignees_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/assignees{/user}","branches_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/branches{/branch}","tags_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/tags","blobs_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/git/refs{/sha}","trees_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/git/trees{/sha}","statuses_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/statuses/{sha}","languages_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/languages","stargazers_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/stargazers","contributors_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/contributors","subscribers_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/subscribers","subscription_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/subscription","commits_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/commits{/sha}","git_commits_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/git/commits{/sha}","comments_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/comments{/number}","issue_comment_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/comments{/number}","contents_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/contents/{+path}","compare_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/compare/{base}...{head}","merges_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/merges","archive_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/downloads","issues_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues{/number}","pulls_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls{/number}","milestones_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/milestones{/number}","notifications_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/labels{/name}","releases_url":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/releases{/id}","created_at":"2014-11-12T02:52:20Z","updated_at":"2015-04-18T09:36:54Z","pushed_at":"2015-04-18T08:16:06Z","git_url":"git://github.com/letsencrypt/lets-encrypt-preview.git","ssh_url":"git@github.com:letsencrypt/lets-encrypt-preview.git","clone_url":"https://github.com/letsencrypt/lets-encrypt-preview.git","svn_url":"https://github.com/letsencrypt/lets-encrypt-preview","homepage":null,"size":6508,"stargazers_count":1800,"watchers_count":1800,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":121,"mirror_url":null,"open_issues_count":73,"forks":121,"open_issues":73,"watchers":1800,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351"},"html":{"href":"https://github.com/letsencrypt/lets-encrypt-preview/pull/351"},"issue":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/351"},"comments":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/issues/351/comments"},"review_comments":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351/comments"},"review_comment":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/pulls/351/commits"},"statuses":{"href":"https://api.github.com/repos/letsencrypt/lets-encrypt-preview/statuses/636f5aa313a617c296251886eb3d58bf4dc32657"}}}}