{"action":"created","comment":{"url":"https://api.github.com/repos/pydata/xarray/pulls/comments/64514575","id":64514575,"diff_hunk":"@@ -1,173 +1,368 @@\n-from .alignment import align, partial_align, align_variables\n-from .utils import ChainMap\n-from .variable import as_variable\n+from collections import defaultdict, deque\n+\n+import pandas as pd\n+\n+from .alignment import align, deep_align\n+from .utils import ChainMap, Frozen\n+from .variable import as_variable, Coordinate, Variable, default_index_coordinate\n from .pycompat import (basestring, iteritems, OrderedDict)\n \n \n-def _as_dataset_variable(name, var):\n-    \"\"\"Prepare a variable for adding it to a Dataset\n+def broadcast_dimension_size(variables):\n+    # type: (List[Variable],) -> Variable\n+    \"\"\"Extract common dimension sizes from a dictionary of variables.\n     \"\"\"\n-    try:\n-        var = as_variable(var, key=name)\n-    except TypeError:\n-        raise TypeError('variables must be given by arrays or a tuple of '\n-                        'the form (dims, data[, attrs, encoding])')\n-    if name in var.dims:\n-        # convert the into an Index\n-        if var.ndim != 1:\n-            raise ValueError('the variable %r has the same name as one of its '\n-                             'dimensions %r, but it is not 1-dimensional and '\n-                             'thus it is not a valid index' % (name, var.dims))\n-        var = var.to_coord()\n-    return var\n-\n-\n-def expand_variables(raw_variables, old_variables=None, compat='identical'):\n-    \"\"\"Expand a dictionary of variables.\n-\n-    Returns a dictionary of Variable objects suitable for inserting into a\n-    Dataset._variables dictionary.\n-\n-    This includes converting tuples (dims, data) into Variable objects,\n-    converting coordinate variables into Coordinate objects and expanding\n-    DataArray objects into Variables plus coordinates.\n-\n-    Raises ValueError if any conflicting values are found, between any of the\n-    new or old variables.\n+    dims = OrderedDict()\n+    for var in variables:\n+        for dim, size in zip(var.dims, var.shape):\n+            if dim in dims and size != dims[dim]:\n+                raise ValueError('index %r not aligned' % dim)\n+            dims[dim] = size\n+    return dims\n+\n+\n+class MergeError(ValueError):\n+    \"\"\"Error class for merge failures due to incompatible arguments.\n     \"\"\"\n-    if old_variables is None:\n-        old_variables = {}\n-    new_variables = OrderedDict()\n-    new_coord_names = set()\n-    variables = ChainMap(new_variables, old_variables)\n-\n-    def maybe_promote_or_replace(name, var):\n-        existing_var = variables[name]\n-        if name not in existing_var.dims:\n-            if name in var.dims:\n-                variables[name] = var\n+    # inherits from ValueError for backward compatibility\n+    # TODO: move this to an xarray.exceptions module?\n+\n+\n+def unique_variable(name, variables, compat='broadcast_equals'):\n+    # type: (Any, List[Variable], str) -> Variable\n+    \"\"\"Return the unique variable from a list of variables or raise MergeError.\n+    \"\"\"\n+    out = variables[0]\n+    if len(variables) > 1:\n+        if compat == 'minimal':\n+            compat = 'broadcast_equals'\n+\n+        if compat == 'broadcast_equals':\n+            dim_lengths = broadcast_dimension_size(variables)\n+            out = out.expand_dims(dim_lengths)\n+\n+        for var in variables[1:]:\n+            if not getattr(out, compat)(var):\n+                raise MergeError('conflicting value for variable %s:\\n'\n+                                 'first value: %r\\nsecond value: %r'\n+                                 % (name, out, var))\n+    return out\n+\n+\n+_VALID_COMPAT = Frozen({'identical': 0,\n+                        'equals': 1,\n+                        'broadcast_equals': 2,\n+                        'minimal': 3})\n+\n+\n+class OrderedDefaultDict(OrderedDict):\n+    # minimal version of an ordered defaultdict\n+    # beware: does not pickle or copy properly\n+    def __init__(self, default_factory):\n+        self.default_factory = default_factory\n+        super(OrderedDefaultDict, self).__init__()\n+\n+    def __missing__(self, key):\n+        self[key] = default = self.default_factory()\n+        return default\n+\n+\n+def get_top_priority_variable(priority_arg=None):\n+    if priority_arg is not None:\n+        # one of these arguments (e.g., the first for in-place\n+        # arithmetic or the second for Dataset.update) takes priority\n+        priority_variables = list_of_variables_dicts[priority_arg]\n+    else:\n+        priority_variables = {}\n+\n+\n+\n+def merge_variables(\n+        list_of_variables_dicts,  # type: List[Mapping[Any, Variable]]\n+        priority_vars=None,       # type: Optional[int]\n+        compat='minimal',         # type: str\n+        ):\n+    # type: (...) -> Dict[Any, Variable]\n+    \"\"\"Merge dicts of variables, while resolving conflicts appropriately.\n+    \"\"\"\n+    if priority_vars is None:\n+        # one of these arguments (e.g., the first for in-place\n+        # arithmetic or the second for Dataset.update) takes priority\n+        priority_vars = {}\n+\n+    assert compat in _VALID_COMPAT","path":"xarray/core/merge.py","position":136,"original_position":136,"commit_id":"02b14f9ebb5ef579f39da1e88550a67ecb6e6bfc","original_commit_id":"02b14f9ebb5ef579f39da1e88550a67ecb6e6bfc","user":{"login":"jhamman","id":2443309,"avatar_url":"https://avatars.githubusercontent.com/u/2443309?v=3","gravatar_id":"","url":"https://api.github.com/users/jhamman","html_url":"https://github.com/jhamman","followers_url":"https://api.github.com/users/jhamman/followers","following_url":"https://api.github.com/users/jhamman/following{/other_user}","gists_url":"https://api.github.com/users/jhamman/gists{/gist_id}","starred_url":"https://api.github.com/users/jhamman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhamman/subscriptions","organizations_url":"https://api.github.com/users/jhamman/orgs","repos_url":"https://api.github.com/users/jhamman/repos","events_url":"https://api.github.com/users/jhamman/events{/privacy}","received_events_url":"https://api.github.com/users/jhamman/received_events","type":"User","site_admin":false},"body":"consider adding a error message here.","created_at":"2016-05-25T04:47:34Z","updated_at":"2016-05-25T04:47:34Z","html_url":"https://github.com/pydata/xarray/pull/857#discussion_r64514575","pull_request_url":"https://api.github.com/repos/pydata/xarray/pulls/857","_links":{"self":{"href":"https://api.github.com/repos/pydata/xarray/pulls/comments/64514575"},"html":{"href":"https://github.com/pydata/xarray/pull/857#discussion_r64514575"},"pull_request":{"href":"https://api.github.com/repos/pydata/xarray/pulls/857"}}},"pull_request":{"url":"https://api.github.com/repos/pydata/xarray/pulls/857","id":71012950,"html_url":"https://github.com/pydata/xarray/pull/857","diff_url":"https://github.com/pydata/xarray/pull/857.diff","patch_url":"https://github.com/pydata/xarray/pull/857.patch","issue_url":"https://api.github.com/repos/pydata/xarray/issues/857","number":857,"state":"open","locked":false,"title":"xarray.merge function and major refactor for merge logic","user":{"login":"shoyer","id":1217238,"avatar_url":"https://avatars.githubusercontent.com/u/1217238?v=3","gravatar_id":"","url":"https://api.github.com/users/shoyer","html_url":"https://github.com/shoyer","followers_url":"https://api.github.com/users/shoyer/followers","following_url":"https://api.github.com/users/shoyer/following{/other_user}","gists_url":"https://api.github.com/users/shoyer/gists{/gist_id}","starred_url":"https://api.github.com/users/shoyer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shoyer/subscriptions","organizations_url":"https://api.github.com/users/shoyer/orgs","repos_url":"https://api.github.com/users/shoyer/repos","events_url":"https://api.github.com/users/shoyer/events{/privacy}","received_events_url":"https://api.github.com/users/shoyer/received_events","type":"User","site_admin":false},"body":"Fixes #417\r\n\r\nNew top level :py:func:`merge` function allows for combining variables from any number of ``Dataset`` and/or ``DataArray`` variables.\r\n\r\nExample usage:\r\n\r\n    >>> arrays = [xr.DataArray(n, name='var%d' % n) for n in range(5)]\r\n    >>> xr.merge(arrays)\r\n    <xarray.Dataset>\r\n    Dimensions:  ()\r\n    Coordinates:\r\n        *empty*\r\n    Data variables:\r\n        var0     int64 0\r\n        var1     int64 1\r\n        var2     int64 2\r\n        var3     int64 3\r\n        var4     int64 4\r\n\r\nThe internal refactoring also lays the ground work for supporting ufunc-like functions that merge three or more arguments, such as the full form of `where`.\r\n\r\nNotes to any potential reviewers:\r\n\r\nThis doesn't have as much test coverage as I would like, but I did get all the existing functionality working. I'll see if I can add in some more tests for the internal code in `merge.py`. Also, more docstrings is probably a good idea.\r\n\r\nEither way, I'm a bit nervous that I haven't broken things, because frankly I still don't understand exactly how the old code worked (and yes, I wrote it!). So we should probably make a release candidate for xarray v0.8 to avoid the need for a bug fix release shortly afterwards.\r\n\r\ncc @jhamman @MaximilianR","created_at":"2016-05-23T07:00:31Z","updated_at":"2016-05-25T04:47:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2973277a8574b0ecaeae81b6f805107d20998720","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/pydata/xarray/pulls/857/commits","review_comments_url":"https://api.github.com/repos/pydata/xarray/pulls/857/comments","review_comment_url":"https://api.github.com/repos/pydata/xarray/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pydata/xarray/issues/857/comments","statuses_url":"https://api.github.com/repos/pydata/xarray/statuses/02b14f9ebb5ef579f39da1e88550a67ecb6e6bfc","head":{"label":"shoyer:merge-cleanup","ref":"merge-cleanup","sha":"02b14f9ebb5ef579f39da1e88550a67ecb6e6bfc","user":{"login":"shoyer","id":1217238,"avatar_url":"https://avatars.githubusercontent.com/u/1217238?v=3","gravatar_id":"","url":"https://api.github.com/users/shoyer","html_url":"https://github.com/shoyer","followers_url":"https://api.github.com/users/shoyer/followers","following_url":"https://api.github.com/users/shoyer/following{/other_user}","gists_url":"https://api.github.com/users/shoyer/gists{/gist_id}","starred_url":"https://api.github.com/users/shoyer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shoyer/subscriptions","organizations_url":"https://api.github.com/users/shoyer/orgs","repos_url":"https://api.github.com/users/shoyer/repos","events_url":"https://api.github.com/users/shoyer/events{/privacy}","received_events_url":"https://api.github.com/users/shoyer/received_events","type":"User","site_admin":false},"repo":{"id":19869133,"name":"xarray","full_name":"shoyer/xarray","owner":{"login":"shoyer","id":1217238,"avatar_url":"https://avatars.githubusercontent.com/u/1217238?v=3","gravatar_id":"","url":"https://api.github.com/users/shoyer","html_url":"https://github.com/shoyer","followers_url":"https://api.github.com/users/shoyer/followers","following_url":"https://api.github.com/users/shoyer/following{/other_user}","gists_url":"https://api.github.com/users/shoyer/gists{/gist_id}","starred_url":"https://api.github.com/users/shoyer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shoyer/subscriptions","organizations_url":"https://api.github.com/users/shoyer/orgs","repos_url":"https://api.github.com/users/shoyer/repos","events_url":"https://api.github.com/users/shoyer/events{/privacy}","received_events_url":"https://api.github.com/users/shoyer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/shoyer/xarray","description":"Extended arrays for working with scientific datasets in Python. http://xray.readthedocs.org","fork":true,"url":"https://api.github.com/repos/shoyer/xarray","forks_url":"https://api.github.com/repos/shoyer/xarray/forks","keys_url":"https://api.github.com/repos/shoyer/xarray/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shoyer/xarray/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shoyer/xarray/teams","hooks_url":"https://api.github.com/repos/shoyer/xarray/hooks","issue_events_url":"https://api.github.com/repos/shoyer/xarray/issues/events{/number}","events_url":"https://api.github.com/repos/shoyer/xarray/events","assignees_url":"https://api.github.com/repos/shoyer/xarray/assignees{/user}","branches_url":"https://api.github.com/repos/shoyer/xarray/branches{/branch}","tags_url":"https://api.github.com/repos/shoyer/xarray/tags","blobs_url":"https://api.github.com/repos/shoyer/xarray/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shoyer/xarray/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shoyer/xarray/git/refs{/sha}","trees_url":"https://api.github.com/repos/shoyer/xarray/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shoyer/xarray/statuses/{sha}","languages_url":"https://api.github.com/repos/shoyer/xarray/languages","stargazers_url":"https://api.github.com/repos/shoyer/xarray/stargazers","contributors_url":"https://api.github.com/repos/shoyer/xarray/contributors","subscribers_url":"https://api.github.com/repos/shoyer/xarray/subscribers","subscription_url":"https://api.github.com/repos/shoyer/xarray/subscription","commits_url":"https://api.github.com/repos/shoyer/xarray/commits{/sha}","git_commits_url":"https://api.github.com/repos/shoyer/xarray/git/commits{/sha}","comments_url":"https://api.github.com/repos/shoyer/xarray/comments{/number}","issue_comment_url":"https://api.github.com/repos/shoyer/xarray/issues/comments{/number}","contents_url":"https://api.github.com/repos/shoyer/xarray/contents/{+path}","compare_url":"https://api.github.com/repos/shoyer/xarray/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shoyer/xarray/merges","archive_url":"https://api.github.com/repos/shoyer/xarray/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shoyer/xarray/downloads","issues_url":"https://api.github.com/repos/shoyer/xarray/issues{/number}","pulls_url":"https://api.github.com/repos/shoyer/xarray/pulls{/number}","milestones_url":"https://api.github.com/repos/shoyer/xarray/milestones{/number}","notifications_url":"https://api.github.com/repos/shoyer/xarray/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shoyer/xarray/labels{/name}","releases_url":"https://api.github.com/repos/shoyer/xarray/releases{/id}","deployments_url":"https://api.github.com/repos/shoyer/xarray/deployments","created_at":"2014-05-16T20:03:09Z","updated_at":"2016-01-12T19:05:29Z","pushed_at":"2016-05-23T06:54:23Z","git_url":"git://github.com/shoyer/xarray.git","ssh_url":"git@github.com:shoyer/xarray.git","clone_url":"https://github.com/shoyer/xarray.git","svn_url":"https://github.com/shoyer/xarray","homepage":"","size":6481,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"pydata:master","ref":"master","sha":"c9cde62c764251b7d39269e860a4a0553c79630f","user":{"login":"pydata","id":1284191,"avatar_url":"https://avatars.githubusercontent.com/u/1284191?v=3","gravatar_id":"","url":"https://api.github.com/users/pydata","html_url":"https://github.com/pydata","followers_url":"https://api.github.com/users/pydata/followers","following_url":"https://api.github.com/users/pydata/following{/other_user}","gists_url":"https://api.github.com/users/pydata/gists{/gist_id}","starred_url":"https://api.github.com/users/pydata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pydata/subscriptions","organizations_url":"https://api.github.com/users/pydata/orgs","repos_url":"https://api.github.com/users/pydata/repos","events_url":"https://api.github.com/users/pydata/events{/privacy}","received_events_url":"https://api.github.com/users/pydata/received_events","type":"Organization","site_admin":false},"repo":{"id":13221727,"name":"xarray","full_name":"pydata/xarray","owner":{"login":"pydata","id":1284191,"avatar_url":"https://avatars.githubusercontent.com/u/1284191?v=3","gravatar_id":"","url":"https://api.github.com/users/pydata","html_url":"https://github.com/pydata","followers_url":"https://api.github.com/users/pydata/followers","following_url":"https://api.github.com/users/pydata/following{/other_user}","gists_url":"https://api.github.com/users/pydata/gists{/gist_id}","starred_url":"https://api.github.com/users/pydata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pydata/subscriptions","organizations_url":"https://api.github.com/users/pydata/orgs","repos_url":"https://api.github.com/users/pydata/repos","events_url":"https://api.github.com/users/pydata/events{/privacy}","received_events_url":"https://api.github.com/users/pydata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pydata/xarray","description":"N-D labeled arrays and datasets in Python","fork":false,"url":"https://api.github.com/repos/pydata/xarray","forks_url":"https://api.github.com/repos/pydata/xarray/forks","keys_url":"https://api.github.com/repos/pydata/xarray/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pydata/xarray/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pydata/xarray/teams","hooks_url":"https://api.github.com/repos/pydata/xarray/hooks","issue_events_url":"https://api.github.com/repos/pydata/xarray/issues/events{/number}","events_url":"https://api.github.com/repos/pydata/xarray/events","assignees_url":"https://api.github.com/repos/pydata/xarray/assignees{/user}","branches_url":"https://api.github.com/repos/pydata/xarray/branches{/branch}","tags_url":"https://api.github.com/repos/pydata/xarray/tags","blobs_url":"https://api.github.com/repos/pydata/xarray/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pydata/xarray/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pydata/xarray/git/refs{/sha}","trees_url":"https://api.github.com/repos/pydata/xarray/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pydata/xarray/statuses/{sha}","languages_url":"https://api.github.com/repos/pydata/xarray/languages","stargazers_url":"https://api.github.com/repos/pydata/xarray/stargazers","contributors_url":"https://api.github.com/repos/pydata/xarray/contributors","subscribers_url":"https://api.github.com/repos/pydata/xarray/subscribers","subscription_url":"https://api.github.com/repos/pydata/xarray/subscription","commits_url":"https://api.github.com/repos/pydata/xarray/commits{/sha}","git_commits_url":"https://api.github.com/repos/pydata/xarray/git/commits{/sha}","comments_url":"https://api.github.com/repos/pydata/xarray/comments{/number}","issue_comment_url":"https://api.github.com/repos/pydata/xarray/issues/comments{/number}","contents_url":"https://api.github.com/repos/pydata/xarray/contents/{+path}","compare_url":"https://api.github.com/repos/pydata/xarray/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pydata/xarray/merges","archive_url":"https://api.github.com/repos/pydata/xarray/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pydata/xarray/downloads","issues_url":"https://api.github.com/repos/pydata/xarray/issues{/number}","pulls_url":"https://api.github.com/repos/pydata/xarray/pulls{/number}","milestones_url":"https://api.github.com/repos/pydata/xarray/milestones{/number}","notifications_url":"https://api.github.com/repos/pydata/xarray/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pydata/xarray/labels{/name}","releases_url":"https://api.github.com/repos/pydata/xarray/releases{/id}","deployments_url":"https://api.github.com/repos/pydata/xarray/deployments","created_at":"2013-09-30T17:21:10Z","updated_at":"2016-05-21T21:11:15Z","pushed_at":"2016-05-23T19:38:07Z","git_url":"git://github.com/pydata/xarray.git","ssh_url":"git@github.com:pydata/xarray.git","clone_url":"https://github.com/pydata/xarray.git","svn_url":"https://github.com/pydata/xarray","homepage":"http://xarray.pydata.org","size":6659,"stargazers_count":378,"watchers_count":378,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":105,"mirror_url":null,"open_issues_count":160,"forks":105,"open_issues":160,"watchers":378,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pydata/xarray/pulls/857"},"html":{"href":"https://github.com/pydata/xarray/pull/857"},"issue":{"href":"https://api.github.com/repos/pydata/xarray/issues/857"},"comments":{"href":"https://api.github.com/repos/pydata/xarray/issues/857/comments"},"review_comments":{"href":"https://api.github.com/repos/pydata/xarray/pulls/857/comments"},"review_comment":{"href":"https://api.github.com/repos/pydata/xarray/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pydata/xarray/pulls/857/commits"},"statuses":{"href":"https://api.github.com/repos/pydata/xarray/statuses/02b14f9ebb5ef579f39da1e88550a67ecb6e6bfc"}}}}
{"actor":{"display_login":"jhamman"}}