codecov-io: # [Codecov](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=h1) Report
> Merging [#7](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=desc) into [master](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/commit/f0a7640c34dcb591b5a0d39148384e257c9a20ac?src=pr&el=desc) will **increase** coverage by `0.12%`.
> The diff coverage is `45.45%`.

[![Impacted file tree graph](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7/graphs/tree.svg?width=650&src=pr&token=5Vtd53LMy2&height=150)](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master    #7      +/-   ##
=======================================
+ Coverage   30.87%   31%   +0.12%     
=======================================
  Files           6     6              
  Lines         353   358       +5     
=======================================
+ Hits          109   111       +2     
- Misses        244   247       +3
```


| [Impacted Files](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [bqdm/action.py](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree#diff-YnFkbS9hY3Rpb24ucHk=) | `30.46% <ø> (ø)` | :arrow_up: |
| [bqdm/util.py](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree#diff-YnFkbS91dGlsLnB5) | `53.84% <ø> (-1.33%)` | :arrow_down: |
| [bqdm/cli.py](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree#diff-YnFkbS9jbGkucHk=) | `0% <0%> (ø)` | :arrow_up: |
| [bqdm/model.py](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=tree#diff-YnFkbS9tb2RlbC5weQ==) | `67.07% <50%> (-2.79%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=footer). Last update [f0a7640...565060b](https://codecov.io/gh/laughingman7743/BigQuery-DatasetManager/pull/7?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/README.rst b/README.rst
index ef9cbc1..1b2503f 100644
--- a/README.rst
+++ b/README.rst
@@ -44,6 +44,8 @@ The resource representation of the dataset is described in `YAML format`_.
     description: null
     default_table_expiration_ms: null
     location: US
+    labels:
+        foo: bar
     access_entries:
     -   role: OWNER
         entity_type: specialGroup
@@ -75,6 +77,8 @@ See `the official documentation of BigQuery Datasets`_ for details of key names.
 +----------------+-------------+-----------+---------+----------------------------------------------------------+
 | location                                 | str     | Location in which the dataset is hosted.                 |
 +----------------+-------------+-----------+---------+----------------------------------------------------------+
+| labels                                   | map     | Labels for the dataset.                                  |
++----------------+-------------+-----------+---------+----------------------------------------------------------+
 | access_entries                           | seq     | Represent grant of an access role to an entity.          |
 +----------------+-------------+-----------+---------+----------------------------------------------------------+
 | access_entries | role                    | str     | Role granted to the entity. One of                       |
@@ -277,7 +281,4 @@ Run test multiple Python versions
 TODO
 ----
 
-#. Support labels field (Currently ``google-cloud-bigquery`` `does not support labels field of Datasets`_)
 #. Manage table resources
-
-.. _`does not support labels field of Datasets`: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2931
diff --git a/bqdm/action.py b/bqdm/action.py
index 2ec16c2..c14529a 100644
--- a/bqdm/action.py
+++ b/bqdm/action.py
@@ -1,10 +1,12 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
 import codecs
 import logging
 import os
 import sys
 
 import click
+from future.utils import iteritems
 from google.cloud import bigquery
 
 from bqdm.model import BigQueryDataset
@@ -116,10 +118,18 @@ class DatasetAction(object):
             click.secho('  Changing... {0}'.format(converted.path), fg='yellow')
             for d in diff:
                 click.echo('    {0}'.format(d))
+            old_labels = old_dataset.labels
+            if old_labels:
+                labels = converted.labels.copy()
+                for k, v in iteritems(old_labels):
+                    if k not in labels.keys():
+                        labels[k] = None
+                converted.labels = labels
             self.client.update_dataset(converted, [
                 'friendly_name',
                 'description',
                 'default_table_expiration_ms',
+                'labels',
                 'access_entries'
             ])
             click.echo()
diff --git a/bqdm/cli.py b/bqdm/cli.py
index 5405243..ae91d99 100755
--- a/bqdm/cli.py
+++ b/bqdm/cli.py
@@ -13,7 +13,7 @@ import bqdm.message as msg
 from bqdm import CONTEXT_SETTINGS
 from bqdm.action import DatasetAction
 from bqdm.model import BigQueryDataset, BigQueryAccessEntry
-from bqdm.util import list_local_datasets, ordered_dict_constructor, str_representer
+from bqdm.util import list_local_datasets, str_representer
 
 
 _logger = logging.getLogger(__name__)
@@ -25,7 +25,6 @@ yaml.add_representer(str, str_representer)
 yaml.add_representer(unicode, str_representer)
 yaml.add_representer(BigQueryDataset, BigQueryDataset.represent)
 yaml.add_representer(BigQueryAccessEntry, BigQueryAccessEntry.represent)
-yaml.add_constructor('tag:yaml.org,2002:map', ordered_dict_constructor)
 
 
 @click.group(context_settings=CONTEXT_SETTINGS)
diff --git a/bqdm/model.py b/bqdm/model.py
index c8cd26d..8da3cd3 100644
--- a/bqdm/model.py
+++ b/bqdm/model.py
@@ -9,13 +9,14 @@ from google.cloud.bigquery.dataset import AccessEntry, Dataset
 class BigQueryDataset(object):
 
     def __init__(self, dataset_id, friendly_name, description,
-                 default_table_expiration_ms, location, access_entries):
+                 default_table_expiration_ms, location, labels, access_entries):
         self.dataset_id = dataset_id
         self.friendly_name = friendly_name
         self.description = description
         self.default_table_expiration_ms = default_table_expiration_ms
         self.location = location
-        self.access_entries = access_entries
+        self.labels = labels if labels else None
+        self.access_entries = access_entries if access_entries else None
 
     @staticmethod
     def from_dict(value):
@@ -27,6 +28,7 @@ class BigQueryDataset(object):
                                value.get('description', None),
                                value.get('default_table_expiration_ms', None),
                                value.get('location', None),
+                               value.get('labels', None),
                                access_entries)
 
     @staticmethod
@@ -39,6 +41,7 @@ class BigQueryDataset(object):
                                dataset.description,
                                dataset.default_table_expiration_ms,
                                dataset.location,
+                               dataset.labels,
                                access_entries)
 
     @staticmethod
@@ -52,6 +55,7 @@ class BigQueryDataset(object):
         dataset.description = value.description
         dataset.default_table_expiration_ms = value.default_table_expiration_ms
         dataset.location = value.location
+        dataset.labels = value.labels if value.labels is not None else dict()
         dataset.access_entries = access_entries
         return dataset
 
@@ -65,6 +69,7 @@ class BigQueryDataset(object):
                 ('description', value.description),
                 ('default_table_expiration_ms', value.default_table_expiration_ms),
                 ('location', value.location),
+                ('labels', value.labels),
                 ('access_entries', value.access_entries),
             )
         )
@@ -75,6 +80,8 @@ class BigQueryDataset(object):
                 self.description,
                 self.default_table_expiration_ms,
                 self.location,
+                frozenset(sorted(self.labels.items())) if self.labels is not None
+                else self.labels,
                 frozenset(self.access_entries) if self.access_entries is not None
                 else self.access_entries,)
 
diff --git a/bqdm/util.py b/bqdm/util.py
index b63a9a0..1a28f1e 100644
--- a/bqdm/util.py
+++ b/bqdm/util.py
@@ -4,7 +4,6 @@ import codecs
 import difflib
 import glob
 import os
-from collections import OrderedDict
 
 import click
 import yaml
@@ -15,10 +14,6 @@ def str_representer(_, data):
     return yaml.ScalarNode('tag:yaml.org,2002:str', data)
 
 
-def ordered_dict_constructor(loader, data):
-    return OrderedDict(loader.construct_pairs(data))
-
-
 def dump_dataset(data):
     return yaml.dump(data, default_flow_style=False, indent=4,
                      allow_unicode=True, canonical=False)

Manage labels field
https://github.com/GoogleCloudPlatform/google-cloud-python/pull/4245/files#diff-bafa3d472438f0a46853cc9879265cadR399
diff --git a/tests/__init__.py b/tests/__init__.py
index 95bd52a..f535f26 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,11 +1,11 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
 import yaml
 
-from bqdm.util import ordered_dict_constructor, str_representer
+from bqdm.util import str_representer
 from bqdm.model import BigQueryDataset, BigQueryAccessEntry
 
 
 yaml.add_representer(str, str_representer)
 yaml.add_representer(BigQueryDataset, BigQueryDataset.represent)
 yaml.add_representer(BigQueryAccessEntry, BigQueryAccessEntry.represent)
-yaml.add_constructor('tag:yaml.org,2002:map', ordered_dict_constructor)
diff --git a/tests/test_action.py b/tests/test_action.py
index 16b2cd9..7382fcf 100644
--- a/tests/test_action.py
+++ b/tests/test_action.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
 import unittest
 
 from bqdm.action import DatasetAction
@@ -14,6 +15,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset2 = BigQueryDataset(
@@ -22,6 +24,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
 
@@ -50,6 +53,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset1_2 = BigQueryDataset(
@@ -58,6 +62,7 @@ class TestAction(unittest.TestCase):
             'bar',
             None,
             'UK',
+            None,
             None
         )
         dataset2_1 = BigQueryDataset(
@@ -66,6 +71,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset2_2 = BigQueryDataset(
@@ -74,6 +80,59 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
+            [
+                BigQueryAccessEntry(
+                    None,
+                    'view',
+                    {
+                        'datasetId': 'test',
+                        'projectId': 'test-project',
+                        'tableId': 'test_table'
+                    }
+                )
+            ]
+        )
+        dataset3_1 = BigQueryDataset(
+            'test3',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            {
+                'foo': 'bar'
+            },
+            None
+        )
+        dataset3_2 = BigQueryDataset(
+            'test3',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            None,
+            [
+                BigQueryAccessEntry(
+                    None,
+                    'view',
+                    {
+                        'datasetId': 'test',
+                        'projectId': 'test-project',
+                        'tableId': 'test_table'
+                    }
+                )
+            ]
+        )
+        dataset3_3 = BigQueryDataset(
+            'test3',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            {
+                'aaa': 'bbb',
+                'ccc': 'ddd'
+            },
             [
                 BigQueryAccessEntry(
                     None,
@@ -117,6 +176,36 @@ class TestAction(unittest.TestCase):
         self.assertEqual(actual_count5, 0)
         self.assertEqual(actual_results5, tuple())
 
+        source6 = [dataset3_1, dataset3_2, dataset3_3]
+        target6 = [dataset3_1, dataset3_2, dataset3_3]
+        actual_count6, actual_results6 = DatasetAction.get_change_datasets(source6, target6)
+        self.assertEqual(actual_count6, 0)
+        self.assertEqual(actual_results6, tuple())
+
+        source7 = [dataset3_1]
+        target7 = [dataset3_2]
+        actual_count7, actual_results7 = DatasetAction.get_change_datasets(source7, target7)
+        self.assertEqual(actual_count7, 1)
+        self.assertEqual(actual_results7, tuple([dataset3_2]))
+
+        source8 = [dataset3_1]
+        target8 = [dataset3_3]
+        actual_count8, actual_results8 = DatasetAction.get_change_datasets(source8, target8)
+        self.assertEqual(actual_count8, 1)
+        self.assertEqual(actual_results8, tuple([dataset3_3]))
+
+        source9 = [dataset3_1]
+        target9 = [dataset3_3]
+        actual_count9, actual_results9 = DatasetAction.get_change_datasets(source9, target9)
+        self.assertEqual(actual_count9, 1)
+        self.assertEqual(actual_results9, tuple([dataset3_3]))
+
+        source10 = [dataset3_2]
+        target10 = [dataset3_3]
+        actual_count10, actual_results10 = DatasetAction.get_change_datasets(source10, target10)
+        self.assertEqual(actual_count10, 1)
+        self.assertEqual(actual_results10, tuple([dataset3_3]))
+
     def test_get_destroy_datasets(self):
         dataset1_1 = BigQueryDataset(
             'test1',
@@ -124,6 +213,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset1_2 = BigQueryDataset(
@@ -132,6 +222,7 @@ class TestAction(unittest.TestCase):
             'bar',
             None,
             'UK',
+            None,
             None
         )
         dataset2_1 = BigQueryDataset(
@@ -140,6 +231,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset2_2 = BigQueryDataset(
@@ -148,6 +240,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [
                 BigQueryAccessEntry(
                     None,
@@ -198,6 +291,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset1_2 = BigQueryDataset(
@@ -206,6 +300,7 @@ class TestAction(unittest.TestCase):
             'bar',
             None,
             'UK',
+            None,
             None
         )
         dataset2_1 = BigQueryDataset(
@@ -214,6 +309,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset2_2 = BigQueryDataset(
@@ -222,6 +318,7 @@ class TestAction(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [
                 BigQueryAccessEntry(
                     None,
diff --git a/tests/test_model.py b/tests/test_model.py
index 16dbe16..e58673d 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
 import unittest
 
 from bqdm.model import BigQueryDataset, BigQueryAccessEntry
@@ -13,6 +14,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset2 = BigQueryDataset(
@@ -21,6 +23,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         dataset3 = BigQueryDataset(
@@ -29,6 +32,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'EU',
+            None,
             None
         )
         dataset4 = BigQueryDataset(
@@ -37,8 +41,10 @@ class TestModel(unittest.TestCase):
             'test_description',
             None,
             'EU',
+            None,
             None
         )
+
         self.assertEqual(dataset1, dataset2)
         self.assertNotEqual(dataset1, dataset3)
         self.assertNotEqual(dataset1, dataset4)
@@ -71,6 +77,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1]
         )
         dataset_with_access_entry2 = BigQueryDataset(
@@ -79,6 +86,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry2]
         )
         dataset_with_access_entry3 = BigQueryDataset(
@@ -87,6 +95,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry3]
         )
         dataset_with_access_entry4 = BigQueryDataset(
@@ -95,6 +104,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1]
         )
         dataset_with_access_entry5 = BigQueryDataset(
@@ -103,6 +113,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1, access_entry3]
         )
         dataset_with_access_entry6 = BigQueryDataset(
@@ -111,6 +122,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry3, access_entry1]
         )
         dataset_with_access_entry7 = BigQueryDataset(
@@ -119,8 +131,10 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1, access_entry2]
         )
+
         self.assertEqual(dataset_with_access_entry1, dataset_with_access_entry2)
         self.assertNotEqual(dataset_with_access_entry1, dataset_with_access_entry3)
         self.assertNotEqual(dataset_with_access_entry1, dataset_with_access_entry4)
@@ -136,14 +150,17 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
+
         dataset_from_dict1 = BigQueryDataset.from_dict({
             'dataset_id': 'test',
             'friendly_name': 'test_friendly_name',
             'description': 'test_description',
             'default_table_expiration_ms': 24 * 30 * 60 * 1000,
             'location': 'US',
+            'labels': None,
             'access_entris': None
         })
         dataset_from_dict2 = BigQueryDataset.from_dict({
@@ -152,6 +169,7 @@ class TestModel(unittest.TestCase):
             'description': 'test_description',
             'default_table_expiration_ms': None,
             'location': 'US',
+            'labels': None,
             'access_entries': None
         })
         dataset_from_dict3 = BigQueryDataset.from_dict({
@@ -160,8 +178,10 @@ class TestModel(unittest.TestCase):
             'description': 'test_description',
             'default_table_expiration_ms': None,
             'location': 'US',
+            'labels': None,
             'access_entries': None
         })
+
         self.assertEqual(dataset, dataset_from_dict1)
         self.assertNotEqual(dataset, dataset_from_dict2)
         self.assertNotEqual(dataset, dataset_from_dict3)
@@ -188,6 +208,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1]
         )
         dataset_with_access_entry2 = BigQueryDataset(
@@ -196,6 +217,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry2]
         )
         dataset_with_access_entry3 = BigQueryDataset(
@@ -204,6 +226,7 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1, access_entry2]
         )
         dataset_with_access_entry4 = BigQueryDataset(
@@ -212,14 +235,17 @@ class TestModel(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry1, access_entry1]
         )
+
         dataset_with_access_entry_from_dict1 = BigQueryDataset.from_dict({
             'dataset_id': 'test',
             'friendly_name': 'test_friendly_name',
             'description': 'test_description',
             'default_table_expiration_ms': 24 * 30 * 60 * 1000,
             'location': 'US',
+            'labels': None,
             'access_entries': [
                 {
                     'role': 'OWNER',
@@ -234,6 +260,7 @@ class TestModel(unittest.TestCase):
             'description': 'test_description',
             'default_table_expiration_ms': 24 * 30 * 60 * 1000,
             'location': 'US',
+            'labels': None,
             'access_entries': [
                 {
                     'role': None,
@@ -252,6 +279,7 @@ class TestModel(unittest.TestCase):
             'description': 'test_description',
             'default_table_expiration_ms': 24 * 30 * 60 * 1000,
             'location': 'US',
+            'labels': None,
             'access_entries': [
                 {
                     'role': 'OWNER',
@@ -275,6 +303,7 @@ class TestModel(unittest.TestCase):
             'description': 'test_description',
             'default_table_expiration_ms': 24 * 30 * 60 * 1000,
             'location': 'US',
+            'labels': None,
             'access_entries': [
                 {
                     'role': 'OWNER',
@@ -288,6 +317,7 @@ class TestModel(unittest.TestCase):
                 }
             ]
         })
+
         self.assertEqual(dataset_with_access_entry1, dataset_with_access_entry_from_dict1)
         self.assertNotEqual(dataset_with_access_entry1, dataset_with_access_entry_from_dict2)
         self.assertNotEqual(dataset_with_access_entry1, dataset_with_access_entry_from_dict3)
@@ -300,3 +330,60 @@ class TestModel(unittest.TestCase):
         self.assertEqual(dataset_with_access_entry4, dataset_with_access_entry_from_dict4)
         self.assertEqual(dataset_with_access_entry1, dataset_with_access_entry_from_dict4)
         self.assertEqual(dataset_with_access_entry4, dataset_with_access_entry_from_dict1)
+
+    def test_dataset_from_dict_with_label(self):
+        label1 = {
+            'foo': 'bar'
+        }
+        label2 = {
+            'aaa': 'bbb',
+            'ccc': 'ddd'
+        }
+
+        dataset_with_label1 = BigQueryDataset(
+            'test',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            label1,
+            None
+        )
+        dataset_with_label2 = BigQueryDataset(
+            'test',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            label2,
+            None
+        )
+
+        dataset_with_label_from_dict1 = BigQueryDataset.from_dict({
+            'dataset_id': 'test',
+            'friendly_name': 'test_friendly_name',
+            'description': 'test_description',
+            'default_table_expiration_ms': 24 * 30 * 60 * 1000,
+            'location': 'US',
+            'labels': {
+                'foo': 'bar'
+            },
+            'access_entries': None
+        })
+        dataset_with_label_from_dict2 = BigQueryDataset.from_dict({
+            'dataset_id': 'test',
+            'friendly_name': 'test_friendly_name',
+            'description': 'test_description',
+            'default_table_expiration_ms': 24 * 30 * 60 * 1000,
+            'location': 'US',
+            'labels': {
+                'aaa': 'bbb',
+                'ccc': 'ddd'
+            },
+            'access_entries': None
+        })
+
+        self.assertEqual(dataset_with_label1, dataset_with_label_from_dict1)
+        self.assertNotEqual(dataset_with_label1, dataset_with_label_from_dict2)
+        self.assertNotEqual(dataset_with_label2, dataset_with_label_from_dict1)
+        self.assertEqual(dataset_with_label2, dataset_with_label_from_dict2)
diff --git a/tests/test_util.py b/tests/test_util.py
index a122afc..b1d29b5 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
 import unittest
 
 from bqdm.model import BigQueryDataset, BigQueryAccessEntry
@@ -14,6 +15,7 @@ class TestUtil(unittest.TestCase):
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             None
         )
         actual_dump_data1 = dump_dataset(dataset1)
@@ -22,6 +24,7 @@ friendly_name: test_friendly_name
 description: test_description
 default_table_expiration_ms: 43200000
 location: US
+labels: null
 access_entries: null
 """
         self.assertEqual(actual_dump_data1, expected_dump_data1)
@@ -37,6 +40,7 @@ access_entries: null
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry2]
         )
         actual_dump_data2 = dump_dataset(dataset2)
@@ -45,6 +49,7 @@ friendly_name: test_friendly_name
 description: test_description
 default_table_expiration_ms: 43200000
 location: US
+labels: null
 access_entries:
 -   role: OWNER
     entity_type: specialGroup
@@ -67,6 +72,7 @@ access_entries:
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry3]
         )
         actual_dump_data3 = dump_dataset(dataset3)
@@ -75,6 +81,7 @@ friendly_name: test_friendly_name
 description: test_description
 default_table_expiration_ms: 43200000
 location: US
+labels: null
 access_entries:
 -   role: null
     entity_type: view
@@ -91,6 +98,7 @@ access_entries:
             'test_description',
             24 * 30 * 60 * 1000,
             'US',
+            None,
             [access_entry2, access_entry3]
         )
         actual_dump_data4 = dump_dataset(dataset4)
@@ -99,6 +107,7 @@ friendly_name: test_friendly_name
 description: test_description
 default_table_expiration_ms: 43200000
 location: US
+labels: null
 access_entries:
 -   role: OWNER
     entity_type: specialGroup
@@ -111,3 +120,53 @@ access_entries:
         tableId: test_table
 """
         self.assertEqual(actual_dump_data4, expected_dump_data4)
+
+        label5 = {
+            'foo': 'bar'
+        }
+        dataset5 = BigQueryDataset(
+            'test5',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            label5,
+            None
+        )
+        actual_dump_data5 = dump_dataset(dataset5)
+        expected_dump_data5 = """dataset_id: test5
+friendly_name: test_friendly_name
+description: test_description
+default_table_expiration_ms: 43200000
+location: US
+labels:
+    foo: bar
+access_entries: null
+"""
+        self.assertEqual(actual_dump_data5, expected_dump_data5)
+
+        label6 = {
+            'aaa': 'bbb',
+            'ccc': 'ddd'
+        }
+        dataset6 = BigQueryDataset(
+            'test6',
+            'test_friendly_name',
+            'test_description',
+            24 * 30 * 60 * 1000,
+            'US',
+            label6,
+            None
+        )
+        actual_dump_data6 = dump_dataset(dataset6)
+        expected_dump_data6 = """dataset_id: test6
+friendly_name: test_friendly_name
+description: test_description
+default_table_expiration_ms: 43200000
+location: US
+labels:
+    aaa: bbb
+    ccc: ddd
+access_entries: null
+"""
+        self.assertEqual(actual_dump_data6, expected_dump_data6)

pip install -e .
parse_log_pytest
pytest
pytest pytest-cov pytest-flake8 pytest-catchlog
apt-get update apt-get install -y gcc
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
-e git+https://github.com/laughingman7743/BigQuery-DatasetManager.git@f0a7640c34dcb591b5a0d39148384e257c9a20ac#egg=BigQuery_DatasetManager
cachetools==4.2.4
certifi==2021.5.30
charset-normalizer==2.0.12
click==8.0.4
coverage==6.2
flake8==5.0.4
future==1.0.0
google-api-core==0.1.4
google-auth==1.35.0
google-cloud-bigquery==0.28.0
google-cloud-core==0.28.1
google-crc32c==1.3.0
google-resumable-media==2.3.3
googleapis-common-protos==1.56.3
idna==3.10
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mccabe==0.7.0
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
protobuf==3.19.6
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyasn1==0.5.1
pyasn1-modules==0.3.0
pycodestyle==2.9.1
pyflakes==2.5.0
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==7.0.1
pytest-catchlog==1.2.2
pytest-cov==4.0.0
pytest-flake8==1.1.1
pytz==2025.2
PyYAML==6.0.1
requests==2.27.1
rsa==4.9
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==1.2.3
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
urllib3==1.26.20
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: BigQuery-DatasetManager
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - cachetools==4.2.4
      - charset-normalizer==2.0.12
      - click==8.0.4
      - coverage==6.2
      - flake8==5.0.4
      - future==1.0.0
      - google-api-core==0.1.4
      - google-auth==1.35.0
      - google-cloud-bigquery==0.28.0
      - google-cloud-core==0.28.1
      - google-crc32c==1.3.0
      - google-resumable-media==2.3.3
      - googleapis-common-protos==1.56.3
      - idna==3.10
      - importlib-metadata==4.2.0
      - mccabe==0.7.0
      - protobuf==3.19.6
      - pyasn1==0.5.1
      - pyasn1-modules==0.3.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pytest==7.0.1
      - pytest-catchlog==1.2.2
      - pytest-cov==4.0.0
      - pytest-flake8==1.1.1
      - pytz==2025.2
      - pyyaml==6.0.1
      - requests==2.27.1
      - rsa==4.9
      - six==1.17.0
      - tomli==1.2.3
      - urllib3==1.26.20
prefix: /opt/conda/envs/BigQuery-DatasetManager

tests/test_action.py::TestAction::test_get_add_datasets tests/test_action.py::TestAction::test_get_change_datasets tests/test_action.py::TestAction::test_get_destroy_datasets tests/test_action.py::TestAction::test_get_intersection_datasets tests/test_model.py::TestModel::test_dataset_from_dict tests/test_model.py::TestModel::test_dataset_from_dict_with_access_entry tests/test_model.py::TestModel::test_dataset_from_dict_with_label tests/test_model.py::TestModel::test_eq_dataset tests/test_model.py::TestModel::test_eq_dataset_with_access_entry tests/test_util.py::TestUtil::test_dump_dataset
README.rst bqdm/cli.py bqdm/model.py bqdm/action.py bqdm/util.py
README.rst bqdm/cli.py bqdm/model.py bqdm/action.py bqdm/util.py