{"action":"created","comment":{"url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/comments/78472240","id":78472240,"diff_hunk":"@@ -0,0 +1,169 @@\n+import logging\n+import threading\n+import re\n+from mongo_connector import errors\n+\n+\n+LOG = logging.getLogger(__name__)\n+\n+\"\"\"New structure to handle both plain and\n+wildcard mapping namespaces dynamically.\n+\"\"\"\n+\n+\n+class DestMapping():\n+    def __init__(self, namespace_set, ex_namespace_set, user_mapping):\n+        \"\"\"\n+            namespace_set and ex_namespace_set will not be non-empty\n+            in the same time.\n+            user_mapping should be non-empty together with namespace_set.\n+            This assumption has been verified in the get_config_options()\n+            in connector.py.\n+        \"\"\"\n+        # a dict containing plain mappings\n+        self.plain = {}\n+        # a dict containing wildcard mappings\n+        self.wildcard = {}\n+        # a dict containing reverse plain mapping\n+        # because the mappings are not duplicated,\n+        # so the values should also be unique\n+        self.reverse_plain = {}\n+        # a dict containing plain db mappings, db -> a set of mapped db\n+        self.plain_db = {}\n+\n+        # the input namespace_set and ex_namespace_set could contain wildcard\n+        self.namespace_set = namespace_set\n+        self.ex_namespace_set = ex_namespace_set\n+\n+        self.lock = threading.Lock()\n+\n+        # initialize\n+        for ns in namespace_set:\n+            user_mapping.setdefault(ns, ns)\n+\n+        for k, v in user_mapping.items():\n+            self.set(k, v)\n+\n+    def set_plain(self, key, value):\n+        \"\"\"A utility function to set the corresponding plain variables\"\"\"\n+        db, col = key.split(\".\", 1)\n+        self.plain[key] = value\n+        self.reverse_plain[value] = key\n+        if col != \"$cmd\":\n+            if db not in self.plain_db:\n+                self.plain_db[db] = set([value.split(\".\")[0]])\n+            else:\n+                self.plain_db[db].add(value.split(\".\")[0])\n+\n+    def match(self, src, dst_pattern):\n+        \"\"\"If source string src matches dst, return the matchobject\"\"\"\n+        reg_pattern = r'\\A' + dst_pattern.replace('*', '(.*)') + r'\\Z'\n+        m = re.match(reg_pattern, src)\n+        return m\n+\n+    def match_set(self, plain_src, dst_arr):\n+        for x in dst_arr:\n+            if plain_src == x:\n+                return True\n+            if \"*\" in x:\n+                m = self.match(plain_src, x)\n+                if m:\n+                    return True\n+\n+        return False\n+\n+    def replace(self, src_match, map_pattern):\n+        \"\"\"Given the matchobject src_match,\n+        replace corresponding '*' in map_pattern with src_match.\"\"\"\n+        wildcard_matched = src_match.group(1)\n+        return map_pattern.replace(\"*\", wildcard_matched)\n+\n+    def get(self, plain_src_ns, defaultval=\"\"):\n+        \"\"\"Given a plain source namespace, return a mapped namespace if matched.\n+        If no match and given defaultval, return it as a default value.\n+        \"\"\"\n+        self.lock.acquire()\n+        # search in plain mappings first\n+        if plain_src_ns in self.plain.keys():\n+            self.lock.release()\n+            return self.plain[plain_src_ns]\n+        else:\n+            # search in wildcard mappings\n+            # if matched, get a replaced mapped namespace\n+            # and add to the plain mappings\n+            for k, v in self.wildcard.items():\n+                m_res = self.match(plain_src_ns, k)\n+                if m_res:\n+                    res = self.replace(m_res, v)\n+                    if res is not None:\n+                        if res not in self.reverse_plain:\n+                            self.set_plain(plain_src_ns, res)\n+                            self.lock.release()\n+                            return res\n+                        else:\n+                            self.lock.release()\n+                            raise errors.InvalidConfiguration(\n+                                \"Destination namespaces set wildcard pattern\"\n+                                \" conflicts with the plain pattern.\")\n+\n+        if defaultval:\n+            self.lock.release()\n+            return defaultval\n+        else:\n+            self.lock.release()\n+            LOG.warn(\"Failed to find matched mapping for %s.\" % plain_src_ns)\n+            return None\n+\n+    def set(self, key, value):\n+        \"\"\"Set the DestMapping instance to corresponding dictionary\"\"\"\n+        self.lock.acquire()","path":"mongo_connector/dest_mapping.py","position":119,"original_position":119,"commit_id":"9129eec53b4c5e16aec4849fdc85c84c7fcbe397","original_commit_id":"9129eec53b4c5e16aec4849fdc85c84c7fcbe397","user":{"login":"ShaneHarvey","id":5015933,"avatar_url":"https://avatars.githubusercontent.com/u/5015933?v=3","gravatar_id":"","url":"https://api.github.com/users/ShaneHarvey","html_url":"https://github.com/ShaneHarvey","followers_url":"https://api.github.com/users/ShaneHarvey/followers","following_url":"https://api.github.com/users/ShaneHarvey/following{/other_user}","gists_url":"https://api.github.com/users/ShaneHarvey/gists{/gist_id}","starred_url":"https://api.github.com/users/ShaneHarvey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ShaneHarvey/subscriptions","organizations_url":"https://api.github.com/users/ShaneHarvey/orgs","repos_url":"https://api.github.com/users/ShaneHarvey/repos","events_url":"https://api.github.com/users/ShaneHarvey/events{/privacy}","received_events_url":"https://api.github.com/users/ShaneHarvey/received_events","type":"User","site_admin":false},"body":"Acquire the lock using a with statement to simplify this code. See, https://docs.python.org/2/library/threading.html#using-locks-conditions-and-semaphores-in-the-with-statement","created_at":"2016-09-12T23:16:03Z","updated_at":"2016-09-12T23:16:03Z","html_url":"https://github.com/mongodb-labs/mongo-connector/pull/495#discussion_r78472240","pull_request_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495","_links":{"self":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/comments/78472240"},"html":{"href":"https://github.com/mongodb-labs/mongo-connector/pull/495#discussion_r78472240"},"pull_request":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495"}}},"pull_request":{"url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495","id":78489510,"html_url":"https://github.com/mongodb-labs/mongo-connector/pull/495","diff_url":"https://github.com/mongodb-labs/mongo-connector/pull/495.diff","patch_url":"https://github.com/mongodb-labs/mongo-connector/pull/495.patch","issue_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/495","number":495,"state":"open","locked":false,"title":"Support wildcard feature in namespaces.include/exclude/mapping","user":{"login":"weixili","id":20318762,"avatar_url":"https://avatars.githubusercontent.com/u/20318762?v=3","gravatar_id":"","url":"https://api.github.com/users/weixili","html_url":"https://github.com/weixili","followers_url":"https://api.github.com/users/weixili/followers","following_url":"https://api.github.com/users/weixili/following{/other_user}","gists_url":"https://api.github.com/users/weixili/gists{/gist_id}","starred_url":"https://api.github.com/users/weixili/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weixili/subscriptions","organizations_url":"https://api.github.com/users/weixili/orgs","repos_url":"https://api.github.com/users/weixili/repos","events_url":"https://api.github.com/users/weixili/events{/privacy}","received_events_url":"https://api.github.com/users/weixili/received_events","type":"User","site_admin":false},"body":"Support configuration for example:\r\n\r\n\"namespaces\": {\r\n\t\t\"include\": [\r\n\t\t  \"foo.\\*\"\r\n\t\t],\r\n\t\t\"exclude\": [\r\n\t      \"foo.jobs\"\r\n\t    ],\r\n\t    \"mapping\": {\r\n\t      \"foo.\\*\": \"foo000_\\*.documents\"\r\n\t    }\r\n\t}\r\n\r\nMore details please see related issues:\r\nhttps://github.com/mongodb-labs/mongo-connector/issues/488\r\nhttps://github.com/mongodb-labs/mongo-connector/issues/480","created_at":"2016-07-22T14:50:10Z","updated_at":"2016-09-12T23:16:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"412ee4262dd976541cc8c9de1fcc61378993fb84","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495/commits","review_comments_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495/comments","review_comment_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/495/comments","statuses_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/statuses/9129eec53b4c5e16aec4849fdc85c84c7fcbe397","head":{"label":"weixili:wildcard-feature","ref":"wildcard-feature","sha":"9129eec53b4c5e16aec4849fdc85c84c7fcbe397","user":{"login":"weixili","id":20318762,"avatar_url":"https://avatars.githubusercontent.com/u/20318762?v=3","gravatar_id":"","url":"https://api.github.com/users/weixili","html_url":"https://github.com/weixili","followers_url":"https://api.github.com/users/weixili/followers","following_url":"https://api.github.com/users/weixili/following{/other_user}","gists_url":"https://api.github.com/users/weixili/gists{/gist_id}","starred_url":"https://api.github.com/users/weixili/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weixili/subscriptions","organizations_url":"https://api.github.com/users/weixili/orgs","repos_url":"https://api.github.com/users/weixili/repos","events_url":"https://api.github.com/users/weixili/events{/privacy}","received_events_url":"https://api.github.com/users/weixili/received_events","type":"User","site_admin":false},"repo":{"id":63952852,"name":"mongo-connector","full_name":"weixili/mongo-connector","owner":{"login":"weixili","id":20318762,"avatar_url":"https://avatars.githubusercontent.com/u/20318762?v=3","gravatar_id":"","url":"https://api.github.com/users/weixili","html_url":"https://github.com/weixili","followers_url":"https://api.github.com/users/weixili/followers","following_url":"https://api.github.com/users/weixili/following{/other_user}","gists_url":"https://api.github.com/users/weixili/gists{/gist_id}","starred_url":"https://api.github.com/users/weixili/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weixili/subscriptions","organizations_url":"https://api.github.com/users/weixili/orgs","repos_url":"https://api.github.com/users/weixili/repos","events_url":"https://api.github.com/users/weixili/events{/privacy}","received_events_url":"https://api.github.com/users/weixili/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/weixili/mongo-connector","description":null,"fork":true,"url":"https://api.github.com/repos/weixili/mongo-connector","forks_url":"https://api.github.com/repos/weixili/mongo-connector/forks","keys_url":"https://api.github.com/repos/weixili/mongo-connector/keys{/key_id}","collaborators_url":"https://api.github.com/repos/weixili/mongo-connector/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/weixili/mongo-connector/teams","hooks_url":"https://api.github.com/repos/weixili/mongo-connector/hooks","issue_events_url":"https://api.github.com/repos/weixili/mongo-connector/issues/events{/number}","events_url":"https://api.github.com/repos/weixili/mongo-connector/events","assignees_url":"https://api.github.com/repos/weixili/mongo-connector/assignees{/user}","branches_url":"https://api.github.com/repos/weixili/mongo-connector/branches{/branch}","tags_url":"https://api.github.com/repos/weixili/mongo-connector/tags","blobs_url":"https://api.github.com/repos/weixili/mongo-connector/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/weixili/mongo-connector/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/weixili/mongo-connector/git/refs{/sha}","trees_url":"https://api.github.com/repos/weixili/mongo-connector/git/trees{/sha}","statuses_url":"https://api.github.com/repos/weixili/mongo-connector/statuses/{sha}","languages_url":"https://api.github.com/repos/weixili/mongo-connector/languages","stargazers_url":"https://api.github.com/repos/weixili/mongo-connector/stargazers","contributors_url":"https://api.github.com/repos/weixili/mongo-connector/contributors","subscribers_url":"https://api.github.com/repos/weixili/mongo-connector/subscribers","subscription_url":"https://api.github.com/repos/weixili/mongo-connector/subscription","commits_url":"https://api.github.com/repos/weixili/mongo-connector/commits{/sha}","git_commits_url":"https://api.github.com/repos/weixili/mongo-connector/git/commits{/sha}","comments_url":"https://api.github.com/repos/weixili/mongo-connector/comments{/number}","issue_comment_url":"https://api.github.com/repos/weixili/mongo-connector/issues/comments{/number}","contents_url":"https://api.github.com/repos/weixili/mongo-connector/contents/{+path}","compare_url":"https://api.github.com/repos/weixili/mongo-connector/compare/{base}...{head}","merges_url":"https://api.github.com/repos/weixili/mongo-connector/merges","archive_url":"https://api.github.com/repos/weixili/mongo-connector/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/weixili/mongo-connector/downloads","issues_url":"https://api.github.com/repos/weixili/mongo-connector/issues{/number}","pulls_url":"https://api.github.com/repos/weixili/mongo-connector/pulls{/number}","milestones_url":"https://api.github.com/repos/weixili/mongo-connector/milestones{/number}","notifications_url":"https://api.github.com/repos/weixili/mongo-connector/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/weixili/mongo-connector/labels{/name}","releases_url":"https://api.github.com/repos/weixili/mongo-connector/releases{/id}","deployments_url":"https://api.github.com/repos/weixili/mongo-connector/deployments","created_at":"2016-07-22T12:48:30Z","updated_at":"2016-07-22T12:48:31Z","pushed_at":"2016-08-30T12:14:10Z","git_url":"git://github.com/weixili/mongo-connector.git","ssh_url":"git@github.com:weixili/mongo-connector.git","clone_url":"https://github.com/weixili/mongo-connector.git","svn_url":"https://github.com/weixili/mongo-connector","homepage":null,"size":2030,"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":"mongodb-labs:master","ref":"master","sha":"f642aa70f7fa8f7cc0d07708e7013ebda3139c74","user":{"login":"mongodb-labs","id":2118794,"avatar_url":"https://avatars.githubusercontent.com/u/2118794?v=3","gravatar_id":"","url":"https://api.github.com/users/mongodb-labs","html_url":"https://github.com/mongodb-labs","followers_url":"https://api.github.com/users/mongodb-labs/followers","following_url":"https://api.github.com/users/mongodb-labs/following{/other_user}","gists_url":"https://api.github.com/users/mongodb-labs/gists{/gist_id}","starred_url":"https://api.github.com/users/mongodb-labs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mongodb-labs/subscriptions","organizations_url":"https://api.github.com/users/mongodb-labs/orgs","repos_url":"https://api.github.com/users/mongodb-labs/repos","events_url":"https://api.github.com/users/mongodb-labs/events{/privacy}","received_events_url":"https://api.github.com/users/mongodb-labs/received_events","type":"Organization","site_admin":false},"repo":{"id":5362729,"name":"mongo-connector","full_name":"mongodb-labs/mongo-connector","owner":{"login":"mongodb-labs","id":2118794,"avatar_url":"https://avatars.githubusercontent.com/u/2118794?v=3","gravatar_id":"","url":"https://api.github.com/users/mongodb-labs","html_url":"https://github.com/mongodb-labs","followers_url":"https://api.github.com/users/mongodb-labs/followers","following_url":"https://api.github.com/users/mongodb-labs/following{/other_user}","gists_url":"https://api.github.com/users/mongodb-labs/gists{/gist_id}","starred_url":"https://api.github.com/users/mongodb-labs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mongodb-labs/subscriptions","organizations_url":"https://api.github.com/users/mongodb-labs/orgs","repos_url":"https://api.github.com/users/mongodb-labs/repos","events_url":"https://api.github.com/users/mongodb-labs/events{/privacy}","received_events_url":"https://api.github.com/users/mongodb-labs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mongodb-labs/mongo-connector","description":"","fork":false,"url":"https://api.github.com/repos/mongodb-labs/mongo-connector","forks_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/forks","keys_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/teams","hooks_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/hooks","issue_events_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/events{/number}","events_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/events","assignees_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/assignees{/user}","branches_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/branches{/branch}","tags_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/tags","blobs_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/git/refs{/sha}","trees_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/statuses/{sha}","languages_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/languages","stargazers_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/stargazers","contributors_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/contributors","subscribers_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/subscribers","subscription_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/subscription","commits_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/commits{/sha}","git_commits_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/git/commits{/sha}","comments_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/comments{/number}","issue_comment_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/comments{/number}","contents_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/contents/{+path}","compare_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/merges","archive_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/downloads","issues_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues{/number}","pulls_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls{/number}","milestones_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/milestones{/number}","notifications_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/labels{/name}","releases_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/releases{/id}","deployments_url":"https://api.github.com/repos/mongodb-labs/mongo-connector/deployments","created_at":"2012-08-09T23:39:36Z","updated_at":"2016-09-09T07:15:11Z","pushed_at":"2016-08-30T12:14:11Z","git_url":"git://github.com/mongodb-labs/mongo-connector.git","ssh_url":"git@github.com:mongodb-labs/mongo-connector.git","clone_url":"https://github.com/mongodb-labs/mongo-connector.git","svn_url":"https://github.com/mongodb-labs/mongo-connector","homepage":null,"size":2722,"stargazers_count":673,"watchers_count":673,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":218,"mirror_url":null,"open_issues_count":68,"forks":218,"open_issues":68,"watchers":673,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495"},"html":{"href":"https://github.com/mongodb-labs/mongo-connector/pull/495"},"issue":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/495"},"comments":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/issues/495/comments"},"review_comments":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495/comments"},"review_comment":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/pulls/495/commits"},"statuses":{"href":"https://api.github.com/repos/mongodb-labs/mongo-connector/statuses/9129eec53b4c5e16aec4849fdc85c84c7fcbe397"}}}}
{"actor":{"display_login":"ShaneHarvey"}}