{"action":"created","comment":{"url":"https://api.github.com/repos/edx/XBlock/pulls/comments/53845413","id":53845413,"diff_hunk":"@@ -260,38 +271,151 @@ def _assert_node_attributes(self, node, expected_attributes):\n             else:\n                 self.assertIsNotNone(node.get(key))\n \n-    def test_add_xml_to_node(self):\n-        \"\"\" Tests add_xml_to_node with various field defaults and runtime parameters \"\"\"\n-        block_type = self.TestXBlock\n-        block = self._make_block(block_type)\n-        node = etree.Element(block_type.etree_node_tag)\n+    def _assert_node_elements(self, node, expected_elements, check_none_attr=True):\n+        \"\"\"\n+        Checks XML node elements to match expected elements.\n+        \"\"\"\n+        node_elements = list(node)\n+        self.assertEqual(set([elem.tag for elem in node_elements]), set(expected_elements.keys()))\n+        if check_none_attr:\n+            # All elements on the node are expected to have a \"none\"=\"true\" attribute.\n+            for elem in node:\n+                self.assertEqual(elem.get('none'), 'true')\n+\n+    def test_no_fields_set_add_xml_to_node(self):\n+        \"\"\"\n+        Tests that no fields are set on a TestXBlock when initially made\n+        and no fields are present in the XML (besides force-exported defaults).\n+        \"\"\"\n+        node = etree.Element(self.test_xblock_tag)\n \n-        # precondition check\n-        for field_name in block.fields.keys():\n-            self.assertFalse(block.fields[field_name].is_set_on(block))\n+        # Precondition check: no fields are set.\n+        for field_name in self.test_xblock.fields.keys():\n+            self.assertFalse(self.test_xblock.fields[field_name].is_set_on(self.test_xblock))\n \n-        block.add_xml_to_node(node)\n+        self.test_xblock.add_xml_to_node(node)\n \n         self._assert_node_attributes(\n-            node, {'simple_force_export': 'default', 'unique_id_force_export': UNIQUE_ID}\n+            node,\n+            {\n+                'str_str_default_force_export': 'default',\n+                'str_uid_default_force_export': UNIQUE_ID\n+            }\n         )\n+        self._assert_node_elements(\n+            node,\n+            {\n+                # The tags are prefixed with {namespace}.\n+                '{{{}}}{}'.format(XML_NAMESPACES[\"option\"], tag): None\n+                for tag in ['str_none_default_force_export']","path":"xblock/test/test_mixins.py","position":94,"original_position":94,"commit_id":"e4adf1e8f227056d07b9b5e5e043e264662d24ba","original_commit_id":"e4adf1e8f227056d07b9b5e5e043e264662d24ba","user":{"login":"doctoryes","id":7285237,"avatar_url":"https://avatars.githubusercontent.com/u/7285237?v=3","gravatar_id":"","url":"https://api.github.com/users/doctoryes","html_url":"https://github.com/doctoryes","followers_url":"https://api.github.com/users/doctoryes/followers","following_url":"https://api.github.com/users/doctoryes/following{/other_user}","gists_url":"https://api.github.com/users/doctoryes/gists{/gist_id}","starred_url":"https://api.github.com/users/doctoryes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doctoryes/subscriptions","organizations_url":"https://api.github.com/users/doctoryes/orgs","repos_url":"https://api.github.com/users/doctoryes/repos","events_url":"https://api.github.com/users/doctoryes/events{/privacy}","received_events_url":"https://api.github.com/users/doctoryes/received_events","type":"User","site_admin":false},"body":"I was following the pattern used elsewhere. But you're right - I'll simplify it.","created_at":"2016-02-23T20:34:44Z","updated_at":"2016-02-23T20:34:44Z","html_url":"https://github.com/edx/XBlock/pull/332#discussion_r53845413","pull_request_url":"https://api.github.com/repos/edx/XBlock/pulls/332","_links":{"self":{"href":"https://api.github.com/repos/edx/XBlock/pulls/comments/53845413"},"html":{"href":"https://github.com/edx/XBlock/pull/332#discussion_r53845413"},"pull_request":{"href":"https://api.github.com/repos/edx/XBlock/pulls/332"}}},"pull_request":{"url":"https://api.github.com/repos/edx/XBlock/pulls/332","id":59704405,"html_url":"https://github.com/edx/XBlock/pull/332","diff_url":"https://github.com/edx/XBlock/pull/332.diff","patch_url":"https://github.com/edx/XBlock/pull/332.patch","issue_url":"https://api.github.com/repos/edx/XBlock/issues/332","number":332,"state":"open","locked":false,"title":"Support XML serialization of None for String field.","user":{"login":"doctoryes","id":7285237,"avatar_url":"https://avatars.githubusercontent.com/u/7285237?v=3","gravatar_id":"","url":"https://api.github.com/users/doctoryes","html_url":"https://github.com/doctoryes","followers_url":"https://api.github.com/users/doctoryes/followers","following_url":"https://api.github.com/users/doctoryes/following{/other_user}","gists_url":"https://api.github.com/users/doctoryes/gists{/gist_id}","starred_url":"https://api.github.com/users/doctoryes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doctoryes/subscriptions","organizations_url":"https://api.github.com/users/doctoryes/orgs","repos_url":"https://api.github.com/users/doctoryes/repos","events_url":"https://api.github.com/users/doctoryes/events{/privacy}","received_events_url":"https://api.github.com/users/doctoryes/received_events","type":"User","site_admin":false},"body":"https://openedx.atlassian.net/browse/PLAT-736\r\n\r\nSee related PR: https://github.com/edx/edx-platform/pull/11490\r\n\r\nAdd ability to send a String field value of `None` to the XBlock's XML representation using a XML attribute on a XML element. Deserialize the `None` value upon loading from XML. Add more testing around String fields with different defaults.\r\n\r\nAlso, fix a bug with caching the default value after deleting an XBlock field.\r\n\r\n@cpennington @adampalay Please review. Anyone else that should review?\r\n@macdiesel FYI.","created_at":"2016-02-17T20:33:29Z","updated_at":"2016-02-23T20:34:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0ea4c4667e021eb9ec03e8a84872ffcff849ccd8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/edx/XBlock/pulls/332/commits","review_comments_url":"https://api.github.com/repos/edx/XBlock/pulls/332/comments","review_comment_url":"https://api.github.com/repos/edx/XBlock/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/XBlock/issues/332/comments","statuses_url":"https://api.github.com/repos/edx/XBlock/statuses/e4adf1e8f227056d07b9b5e5e043e264662d24ba","head":{"label":"edx:jeskew/none_as_attribute_in_xml","ref":"jeskew/none_as_attribute_in_xml","sha":"e4adf1e8f227056d07b9b5e5e043e264662d24ba","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":8710321,"name":"XBlock","full_name":"edx/XBlock","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/XBlock","description":"XBlock courseware component architecture","fork":false,"url":"https://api.github.com/repos/edx/XBlock","forks_url":"https://api.github.com/repos/edx/XBlock/forks","keys_url":"https://api.github.com/repos/edx/XBlock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/XBlock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/XBlock/teams","hooks_url":"https://api.github.com/repos/edx/XBlock/hooks","issue_events_url":"https://api.github.com/repos/edx/XBlock/issues/events{/number}","events_url":"https://api.github.com/repos/edx/XBlock/events","assignees_url":"https://api.github.com/repos/edx/XBlock/assignees{/user}","branches_url":"https://api.github.com/repos/edx/XBlock/branches{/branch}","tags_url":"https://api.github.com/repos/edx/XBlock/tags","blobs_url":"https://api.github.com/repos/edx/XBlock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/XBlock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/XBlock/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/XBlock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/XBlock/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/XBlock/languages","stargazers_url":"https://api.github.com/repos/edx/XBlock/stargazers","contributors_url":"https://api.github.com/repos/edx/XBlock/contributors","subscribers_url":"https://api.github.com/repos/edx/XBlock/subscribers","subscription_url":"https://api.github.com/repos/edx/XBlock/subscription","commits_url":"https://api.github.com/repos/edx/XBlock/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/XBlock/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/XBlock/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/XBlock/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/XBlock/contents/{+path}","compare_url":"https://api.github.com/repos/edx/XBlock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/XBlock/merges","archive_url":"https://api.github.com/repos/edx/XBlock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/XBlock/downloads","issues_url":"https://api.github.com/repos/edx/XBlock/issues{/number}","pulls_url":"https://api.github.com/repos/edx/XBlock/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/XBlock/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/XBlock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/XBlock/labels{/name}","releases_url":"https://api.github.com/repos/edx/XBlock/releases{/id}","deployments_url":"https://api.github.com/repos/edx/XBlock/deployments","created_at":"2013-03-11T18:35:36Z","updated_at":"2016-02-17T16:56:20Z","pushed_at":"2016-02-22T16:49:10Z","git_url":"git://github.com/edx/XBlock.git","ssh_url":"git@github.com:edx/XBlock.git","clone_url":"https://github.com/edx/XBlock.git","svn_url":"https://github.com/edx/XBlock","homepage":null,"size":3722,"stargazers_count":396,"watchers_count":396,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":196,"mirror_url":null,"open_issues_count":26,"forks":196,"open_issues":26,"watchers":396,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"9f616caf86f6349155adbce7f9f2ef58e8b935e3","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":8710321,"name":"XBlock","full_name":"edx/XBlock","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/XBlock","description":"XBlock courseware component architecture","fork":false,"url":"https://api.github.com/repos/edx/XBlock","forks_url":"https://api.github.com/repos/edx/XBlock/forks","keys_url":"https://api.github.com/repos/edx/XBlock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/XBlock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/XBlock/teams","hooks_url":"https://api.github.com/repos/edx/XBlock/hooks","issue_events_url":"https://api.github.com/repos/edx/XBlock/issues/events{/number}","events_url":"https://api.github.com/repos/edx/XBlock/events","assignees_url":"https://api.github.com/repos/edx/XBlock/assignees{/user}","branches_url":"https://api.github.com/repos/edx/XBlock/branches{/branch}","tags_url":"https://api.github.com/repos/edx/XBlock/tags","blobs_url":"https://api.github.com/repos/edx/XBlock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/XBlock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/XBlock/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/XBlock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/XBlock/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/XBlock/languages","stargazers_url":"https://api.github.com/repos/edx/XBlock/stargazers","contributors_url":"https://api.github.com/repos/edx/XBlock/contributors","subscribers_url":"https://api.github.com/repos/edx/XBlock/subscribers","subscription_url":"https://api.github.com/repos/edx/XBlock/subscription","commits_url":"https://api.github.com/repos/edx/XBlock/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/XBlock/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/XBlock/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/XBlock/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/XBlock/contents/{+path}","compare_url":"https://api.github.com/repos/edx/XBlock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/XBlock/merges","archive_url":"https://api.github.com/repos/edx/XBlock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/XBlock/downloads","issues_url":"https://api.github.com/repos/edx/XBlock/issues{/number}","pulls_url":"https://api.github.com/repos/edx/XBlock/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/XBlock/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/XBlock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/XBlock/labels{/name}","releases_url":"https://api.github.com/repos/edx/XBlock/releases{/id}","deployments_url":"https://api.github.com/repos/edx/XBlock/deployments","created_at":"2013-03-11T18:35:36Z","updated_at":"2016-02-17T16:56:20Z","pushed_at":"2016-02-22T16:49:10Z","git_url":"git://github.com/edx/XBlock.git","ssh_url":"git@github.com:edx/XBlock.git","clone_url":"https://github.com/edx/XBlock.git","svn_url":"https://github.com/edx/XBlock","homepage":null,"size":3722,"stargazers_count":396,"watchers_count":396,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":196,"mirror_url":null,"open_issues_count":26,"forks":196,"open_issues":26,"watchers":396,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/XBlock/pulls/332"},"html":{"href":"https://github.com/edx/XBlock/pull/332"},"issue":{"href":"https://api.github.com/repos/edx/XBlock/issues/332"},"comments":{"href":"https://api.github.com/repos/edx/XBlock/issues/332/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/XBlock/pulls/332/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/XBlock/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/XBlock/pulls/332/commits"},"statuses":{"href":"https://api.github.com/repos/edx/XBlock/statuses/e4adf1e8f227056d07b9b5e5e043e264662d24ba"}}}}