Beispiel #1
0
Datei: db.py Projekt: ryde/EDMAN
    def loop_exclusion_key_and_ref(self, collection: str, key: str,
                                   exclusion: tuple) -> dict:
        """
        対象のコレクション内のドキュメントを全て、指定のキーの要素を抜き出してrefに変換してDBに入れる
        また、取り出したデータ内の指定の要素を除外することもできる

        :param str collection: 変換対象のコレクション
        :param str key: refに変換開始する対象のキー
        :param tuple exclusion: 除外するキーの設定
        :return: result
        :rtype: dict
        """
        docs = self.db[collection].find()
        if docs.count() == 0:
            sys.exit('対象のドキュメントは存在しません')
        id_list = []
        for doc in docs:
            if self.get_structure(collection, doc['_id']) == 'emb':
                id_list.append(doc['_id'])

        if len(id_list) == 0:
            sys.exit('変換対象のドキュメントは全てreferenceです')

        result_list = []
        for oid in id_list:
            emb_result = self.db[collection].find_one({'_id': oid})
            del emb_result['_id']
            convert = Convert()
            pull_result = convert.pullout_key(emb_result, key)
            if not pull_result:
                sys.exit(f'{key}は存在しません')
            if exclusion:
                result = convert.exclusion_key(pull_result, exclusion)
                if pull_result == result:
                    sys.exit(f'{list(exclusion)}は存在しません')
            else:
                result = pull_result

            converted_edman = convert.dict_to_edman(result)
            structured_result = self.insert(converted_edman)
            structured_result.reverse()
            result_list.append(structured_result)

        result = {}
        if len(result_list):
            result.update({'result': result_list})
            print('\r\n')  # 改行できない問題を回避

        return result
Beispiel #2
0
Datei: db.py Projekt: ryde/EDMAN
    def update(self, collection: str, oid: Union[str, ObjectId],
               amend_data: dict, structure: str) -> bool:
        """
        修正データを用いてDBデータをアップデート

        :param str collection:
        :param oid:
        :type oid: str or ObjectId
        :param dict amend_data:
        :param str structure:
        :return:
        :rtype: bool
        """

        oid = Utils.conv_objectid(oid)
        db_result = self.db[collection].find_one({'_id': oid})
        if db_result is None:
            sys.exit('該当するドキュメントは存在しません')

        if structure == 'emb':
            try:
                # 日付データを日付オブジェクトに変換するため、
                # 必ずコンバートしてからマージする
                convert = Convert()
                converted_amend_data = convert.emb(amend_data)
                amended = self._merge(db_result, converted_amend_data)
            except ValueError as e:
                sys.exit(e)
        elif structure == 'ref':
            # 日付データを日付オブジェクトに変換
            converted_amend_data = self._convert_datetime_dict(amend_data)
            amended = {**db_result, **converted_amend_data}
        else:
            sys.exit('structureはrefまたはembの指定が必要です')

        try:
            replace_result = self.db[collection].replace_one({'_id': oid},
                                                             amended)
        except errors.OperationFailure:
            sys.exit('アップデートに失敗しました')

        return True if replace_result.modified_count == 1 else False
Beispiel #3
0
 def setUp(self):
     self.convert = Convert()
     self.config = Config()
     self.parent = self.config.parent
     self.child = self.config.child
     self.date = self.config.date
Beispiel #4
0
class TestConvert(TestCase):

    def setUp(self):
        self.convert = Convert()
        self.config = Config()
        self.parent = self.config.parent
        self.child = self.config.child
        self.date = self.config.date

    def test__get_child_reference(self):

        # すでにparentが作られていた場合
        # (この関数後の処理にDBRefオブジェクトが0個の時の処理が書かれているため0個でもOK)
        test_data = {self.parent: {'_id': ObjectId()}}
        actual = self.convert._get_child_reference(test_data)
        self.assertEqual(0, len(list(actual.values())[0]))

        # テスト辞書データの中身が辞書の場合
        test_data = {'test_collection': {'_id': ObjectId()}}
        actual = self.convert._get_child_reference(test_data)
        self.assertIsInstance(actual, dict)
        self.assertEqual(self.config.child, list(actual.keys())[0])
        self.assertEqual(1, len(list(actual.values())[0]))

        # テスト辞書データの中身がリストの場合
        test_data = {
            'test_collection': [
                {'_id': ObjectId()},
                {'_id': ObjectId()}
            ]
        }
        actual = self.convert._get_child_reference(test_data)
        self.assertEqual(2, len(list(actual.values())[0]))

    def test__convert_datetime(self):
        # データ構造のテスト
        test_data = {'start_date': {'#date': '1981-04-23'}}
        actual = self.convert._convert_datetime(test_data)
        self.assertIsInstance(actual, dict)
        self.assertIsInstance(list(actual.values())[0], datetime)

    def test__list_organize(self):
        # データ構造のテスト
        test_data = [
            {
                'honda': [
                    {'name': 'NSX', 'power': '280'}
                ]
            },
            {
                'honda': [
                    {'name': 'S800', 'first model year': '1966'}
                ]
            }
        ]
        actual = self.convert._list_organize(test_data)
        self.assertIsInstance(actual, list)
        self.assertEqual('honda', list(actual[0].keys())[0])
        self.assertEqual(2, len(list(actual[0].values())[0]))
        for i in list(actual[0].values())[0]:
            with self.subTest(i=i):
                self.assertIsInstance(i, dict)

    def test__list_intercept_hook(self):

        data = {
            'parent_data': 'data1',
            'delete_coll': {'data': '1', 'data2': '2'},
            'child': [
                DBRef('test_collection', ObjectId()),
                DBRef('test_collection', ObjectId())]}
        actual = self.convert._list_intercept_hook('test_coll', data)

        # 子要素のデータ(この場合はdata['delete_coll'])が削除されているか
        self.assertIsInstance(actual, dict)
        for k, v in actual.items():
            with self.subTest(v=v):
                self.assertNotIn('delete_coll', v[0])

    def test__attached_oid(self):
        # 辞書内辞書の場合
        test_data = {
            'collection': {
                'car_name': 'NSX',
                'Purchase year': '1993'
            }
        }
        actual = self.convert._attached_oid(test_data)
        self.assertIsInstance(actual, dict)
        self.assertTrue(True if '_id' in list(actual.values())[0] else False)
        self.assertIsInstance(list(actual.values())[0]['_id'], ObjectId)

        # 辞書内リストの場合
        test_data = {
            'collection': [
                {
                    'car_name': 'NSX',
                    'Purchase year': '1993'
                }
            ]
        }
        actual = self.convert._attached_oid(test_data)
        self.assertTrue(
            True if '_id' in list(actual.values())[0][0] else False)
        self.assertIsInstance(list(actual.values())[0][0]['_id'], ObjectId)

    def test__field_name_check(self):

        illegals = [None, '', '$aa', '.aa']
        for i in illegals:
            with self.subTest(i=i):
                actual = self.convert._field_name_check(i)
                self.assertFalse(actual)

        # 文字列以外の方は文字列に変換される
        actual = self.convert._field_name_check(455)
        self.assertTrue(actual)

    def test__date_replace(self):
        list_data = [{self.date: '2019-02-28'},
                     {self.date: '2019-03-01 13:56:28'},
                     1,
                     'text']
        expected = [datetime(2019, 2, 28),
                    datetime(2019, 3, 1, 13, 56, 28),
                    1,
                    'text']
        actual = self.convert._date_replace(list_data)
        self.assertListEqual(expected, actual)

    def test_pullout_key(self):

        data = {
            'beamtime': {
                'username': '******',
                'expInfo': [
                    {
                        'date': '2019-08-02',
                        'position': {'a': '1', 'b': '2'},
                        'file': {'name': 'sample.jpg'},
                        'process': {
                            'cc': '33',
                            'file': {
                                'name': 'machine.log',
                                'file': {'name': 'machine2.log'}
                            }
                        }
                    },
                    {
                        'date': '2019-08-03',
                        'position': {'a': '11', 'b': '22'},
                        'file': {'name': 'process.jpg'},
                        'process': {
                            'cc': '44',
                            'file': {
                                'name': 'machine3.log',
                                'file': {'name': 'machine4.log'}
                            }
                        }
                    },
                ]}
        }
        key = 'expInfo'
        actual = self.convert.pullout_key(data, key)

        expected = {
            'expInfo': [
                {
                    'date': '2019-08-02',
                    'position': {'a': '1', 'b': '2'},
                    'file': {'name': 'sample.jpg'},
                    'process': {
                        'cc': '33',
                        'file': {
                            'name': 'machine.log',
                            'file': {'name': 'machine2.log'}
                        }
                    }
                },
                {
                    'date': '2019-08-03',
                    'position': {'a': '11', 'b': '22'},
                    'file': {'name': 'process.jpg'},
                    'process': {
                        'cc': '44',
                        'file': {
                            'name': 'machine3.log',
                            'file': {'name': 'machine4.log'}
                        }
                    }
                },
            ]}
        self.assertIsInstance(actual, dict)
        self.assertDictEqual(expected, actual)

        # 別のデータ(この場合は1番目のprocessを拾ってくる)
        data2 = {
            'beamtime': {
                'username': '******',
                'expInfo': [
                    {
                        'date': '2019-08-02',
                        'position': {'a': '1', 'b': '2'},
                        'file': {'name': 'sample.jpg'},
                        'process': {
                            'cc': '33',
                            'file': {
                                'name': 'machine.log',
                                'file': {'name': 'machine2.log'}
                            }
                        }
                    },
                    {
                        'date': '2019-08-03',
                        'position': {'a': '11', 'b': '22'},
                        'file': {'name': 'process.jpg'},
                        'process': {
                            'cc': '44',
                            'file': {
                                'name': 'machine3.log',
                                'file': {'name': 'machine4.log'}
                            }
                        }
                    },
                ]}
        }
        key = 'process'
        actual = self.convert.pullout_key(data2, key)
        expected = {
            'process': {
                'cc': '33',
                'file': {
                    'name': 'machine.log',
                    'file': {'name': 'machine2.log'}
                }
            }
        }
        self.assertDictEqual(expected, actual)

        # 指定のキーが見つからなかった時
        key = 'foobar'
        actual = self.convert.pullout_key(data, key)
        self.assertDictEqual({}, actual)

        # データが無かった場合
        data3 = {}
        key = 'expInfo'
        actual = self.convert.pullout_key(data3, key)
        self.assertDictEqual({}, actual)

    def test_exclusion_key(self):
        data = {
            'expInfo': [
                {
                    'date': '2019-08-02',
                    'position': {'a': '1', 'b': '2'},
                    'file': {'name': 'sample.jpg'},
                    'process': {
                        'cc': '33',
                        'file': {
                            'name': 'machine.log',
                            'file': {'name': 'machine2.log'}
                        }
                    }
                },
                {
                    'date': '2019-08-03',
                    'position': {'a': '11', 'b': '22'},
                    'file': {'name': 'process.jpg'},
                    'process': {
                        'cc': '44',
                        'file': {
                            'name': 'machine3.log',
                            'file': {'name': 'machine4.log'}
                        }
                    }
                },
            ]}

        exclusion = ('position',)
        actual = self.convert.exclusion_key(data, exclusion)
        expected = {
            'expInfo': [
                {
                    'date': '2019-08-02',
                    'file': {'name': 'sample.jpg'},
                    'process': {
                        'cc': '33',
                        'file': {
                            'name': 'machine.log',
                            'file': {'name': 'machine2.log'}
                        }
                    }
                },
                {
                    'date': '2019-08-03',
                    'file': {'name': 'process.jpg'},
                    'process': {
                        'cc': '44',
                        'file': {
                            'name': 'machine3.log',
                            'file': {'name': 'machine4.log'}
                        }
                    }
                },
            ]}
        self.assertIsInstance(actual, dict)
        self.assertDictEqual(expected, actual)

        # 指定のキーが見つからなかった時
        exclusion = ('foobar',)
        actual = self.convert.exclusion_key(data, exclusion)
        self.assertDictEqual(data, actual)

    def test__ref(self):
        pass
        # テスト用jsonの読み込み
        # with open('./test_json_files/ref_test_premo.json') as f:
        #     jsondict = json.load(f)
        #
        # actual = self.convert._ref(jsondict)
        #
        # with open('./test_json_files/ref_test_premo_result.json', 'w') as f:
        #     f.write(dumps(actual, ensure_ascii=False, indent=4))
        # TODO あとでテストデータを追加し、assertできるようにする

    def test__emb(self):
        pass
Beispiel #5
0
    def test_add_file_reference(self):
        if not self.db_server_connect:
            return

        # refの場合
        # refデータ入力
        ref_json = {
            "structure_1": [{
                "position":
                "top",
                "username":
                "******",
                "structure_2": [{
                    "maker": "Ferrari",
                    "carname": "F355",
                    "power": 380,
                    "float_val": 4453.456
                }, {
                    "maker":
                    "HONDA",
                    "carname":
                    "NSX",
                    "power":
                    280,
                    "float_val":
                    321.56,
                    "start_date": {
                        "#date": "1981-04-23"
                    },
                    "structure_3_1": [{
                        "filename": "test1.txt",
                        "name": "添付ファイル1"
                    }, {
                        "filename": "test2.txt",
                        "name": "添付ファイル2"
                    }],
                    "structure_3_2": [{
                        "filename":
                        "test3.txt",
                        "name":
                        "添付ファイル3",
                        "structure_4": {
                            "filename":
                            "test4.txt",
                            "name":
                            "添付ファイル4",
                            "structure_5": [{
                                "url": "example2.com",
                                "name": "テストURL2"
                            }, {
                                "url": "example3.com",
                                "name": "テストURL3"
                            }]
                        },
                        "structure_6": [{
                            "url": "example_x.com",
                            "name": "テストURL_x"
                        }, {
                            "url": "example_y.com",
                            "name": "テストURL_y"
                        }],
                        "structure_5": {
                            "url": "example.com",
                            "name": "テストURL1",
                            "structure_5": {
                                "url": "example4.com",
                                "name": "テストURL4"
                            }
                        }
                    }]
                }]
            }]
        }
        convert = Convert()
        converted_edman = convert.dict_to_edman(ref_json, mode='ref')
        insert_result = self.db.insert(converted_edman)

        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)

            expected = []
            for i in range(2):
                gen_file = 'insert_file_ref_test' + str(i) + '.txt'
                gen_path = p / gen_file
                with gen_path.open('w') as f:
                    test_var = 'test' + str(i)
                    expected.append((gen_file, test_var))
                    f.write(test_var)

            file_path = tuple(sorted(p.glob('insert_file_ref_test*.txt')))

            # メソッド実行
            collection = 'structure_5'
            oid = [i[collection][0] for i in insert_result
                   if collection in i][0]
            insert_file_result = self.file.add_file_reference(collection,
                                                              oid,
                                                              file_path,
                                                              'ref',
                                                              compress=True)

            # DBからデータ取得
            query = {'_id': oid}
            result = self.testdb[collection].find_one(query)

            # 取得したデータからgridfsのファイルを取得
            actual = []
            self.fs = gridfs.GridFS(self.testdb)
            for file_oid in result[self.config.file]:
                data = self.fs.get(file_oid)
                d = data.read()
                if hasattr(data, 'compress') and data.compress == 'gzip':
                    d = gzip.decompress(d)
                actual.append((data.filename, d.decode()))

            # テスト
            self.assertTrue(insert_file_result)
            self.assertListEqual(sorted(actual), sorted(expected))

        # embの場合
        data = {
            "position":
            "top",
            "structure_2": [{
                "maker": "Ferrari",
                "carname": "F355",
                "power": 380,
                "float_val": 4453.456
            }, {
                "maker":
                "HONDA",
                "carname":
                "NSX",
                "power":
                280,
                "float_val":
                321.56,
                "structure_3_1": [{
                    "filename": "test1.txt",
                    "name": "添付ファイル1"
                }, {
                    "filename": "test2.txt",
                    "name": "添付ファイル2"
                }],
                "structure_3_2": [{
                    "filename":
                    "test3.txt",
                    "name":
                    "添付ファイル3",
                    "structure_4": {
                        "filename":
                        "test4.txt",
                        "name":
                        "添付ファイル4",
                        "structure_5": [{
                            "url": "example2.com",
                            "name": "テストURL2"
                        }, {
                            "url": "example3.com",
                            "name": "テストURL3"
                        }]
                    },
                    "structure_6": [{
                        "url": "example_x.com",
                        "name": "テストURL_x"
                    }, {
                        "url": "example_y.com",
                        "name": "テストURL_y"
                    }],
                    "structure_5": {
                        "url": "example.com",
                        "name": "テストURL1",
                        "structure_5": {
                            "url": "example4.com",
                            "name": "テストURL4"
                        }
                    }
                }]
            }]
        }
        insert_result = self.testdb['structure_emb'].insert_one(data)

        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)

            expected = []
            for i in range(2):
                gen_file = 'emb_test' + str(i) + '.txt'
                gen_path = p / gen_file
                with gen_path.open('w') as f:
                    test_var = 'test' + str(i)
                    f.write(test_var)
                    expected.append(test_var)
            files = tuple(sorted(p.glob('emb_test*.txt')))
            collection = 'structure_emb'
            oid = insert_result.inserted_id
            query = ['structure_2', '1']

            # メソッド実行
            insert_file_emb_result = self.file.add_file_reference(
                collection, oid, files, 'emb', query, compress=True)
            # ドキュメントをfindして出す
            result = self.testdb[collection].find_one({'_id': oid})

            # gridfsからデータ取得
            out_data = []
            self.fs = gridfs.GridFS(self.testdb)
            for oid in result['structure_2'][1][self.config.file]:
                data = self.fs.get(oid)
                f_data = data.read()
                if hasattr(data, 'compress') and data.compress == 'gzip':
                    f_data = gzip.decompress(f_data)

                out_data.append(f_data.decode())

            # DBデータとファイルのデータに差異はないか
            self.assertListEqual(sorted(expected), sorted(out_data))

            # メソッド成功時のフラグ
            self.assertTrue(insert_file_emb_result)
Beispiel #6
0
Datei: db.py Projekt: ryde/EDMAN
    def structure(self, collection: str, oid: ObjectId,
                  structure_mode: str, new_collection: str) -> list:
        """
        構造をrefからembへ、またはembからrefへ変更する

        :param str collection:
        :param ObjectId oid:
        :param str structure_mode:
        :param str new_collection:
        :return: structured_result
        :rtype: list
        """

        oid = Utils.conv_objectid(oid)

        # refデータをembに変換する
        if structure_mode == 'emb':
            # 自分データ取り出し
            ref_result = self.doc(collection, oid, query=None,
                                  reference_delete=False)
            reference_point_result = self.get_reference_point(
                ref_result)
            if reference_point_result[self.child]:
                # 子データを取り出し
                children = self.get_child_all({collection: ref_result})

                # 自分のリファレンスデータとidを削除
                for del_key in (self.parent, self.child, '_id'):
                    if del_key in ref_result:
                        del ref_result[del_key]

                # 子のリファレンスデータ削除
                non_ref_children = self.delete_reference(children,
                                                         ('_id', self.parent,
                                                          self.child))
                # 自分と子要素をマージする
                ref_result.update(non_ref_children)

                convert = Convert()
                converted_edman = convert.dict_to_edman(
                    {new_collection: ref_result}, mode='emb')
                structured_result = self.insert(converted_edman)
            # 子が存在しないドキュメントの場合(新たなコレクションとして切り出す)
            else:
                # 自分のリファレンスデータとidを削除
                for del_key in (self.parent, '_id'):
                    if del_key in ref_result:
                        del ref_result[del_key]
                convert = Convert()
                converted_edman = convert.dict_to_edman(
                    {new_collection: ref_result}, mode='emb')
                structured_result = self.insert(converted_edman)

        # embからrefに変換
        elif structure_mode == 'ref':
            emb_result = self.db[collection].find_one({'_id': oid})
            del emb_result['_id']
            convert = Convert()
            converted_edman = convert.dict_to_edman(
                {new_collection: emb_result}, mode='ref')
            structured_result = self.insert(converted_edman)
            structured_result.reverse()

        else:
            sys.exit('構造はrefかembを指定してください')

        return structured_result
Beispiel #7
0
    parser.error("--structure requires 'ref' or 'emb'.")

# 結果を記録する場合はパスの存在を調べる
if args.result_dir is not None:
    p = Path(args.result_dir)
    if not p.exists() and not p.is_dir():
        sys.exit('パスが不正です')

# iniファイル読み込み
settings = configparser.ConfigParser()
settings.read(Path.cwd() / 'ini' / 'db.ini')
con = dict([i for i in settings['DB'].items()])

db = DB(con)
jm = JsonManager()
convert = Convert()
json_files = Action.files_read(args.path, 'json')

for file in Action.file_gen(json_files):
    # Ednman用にjsonをコンバート
    converted_edman = convert.dict_to_edman(file, mode=args.structure)
    # コンバート結果を保存する場合
    # jm.save({'converted_edman': converted_edman}, args.result_dir,
    #         name='edman_json_list', date=True)

    # DBへインサート
    inserted_report = db.insert(converted_edman)

    if args.result_dir is not None:
        jm.save({'inserted_report': inserted_report},
                args.result_dir,