Beispiel #1
0
    def setUp(self):

        if self.db_server_connect:
            self.file = File(self.db.get_db)
        else:
            self.file = File()
        self.config = Config()
Beispiel #2
0
Datei: db.py Projekt: ryde/EDMAN
    def _delete_documents_and_files(self, db_result: dict,
                                    collection: str) -> None:
        """
        指定のドキュメント以下の子ドキュメントと関連ファイルを削除する

        :param dict db_result:
        :param str collection:
        :return:
        """
        delete_doc_id_dict = {}
        delete_file_ref_list = []
        for element in [i for i in
                        self._recursive_extract_elements_from_doc(db_result,
                                                                  collection)]:
            doc_collection = list(element.keys())[0]
            id_and_refs = list(element.values())[0]

            for oid, refs in id_and_refs.items():
                if delete_doc_id_dict.get(doc_collection):
                    delete_doc_id_dict[doc_collection].append(oid)
                else:
                    delete_doc_id_dict.update({doc_collection: [oid]})

                if refs.get(self.file_ref):
                    delete_file_ref_list.extend(refs[self.file_ref])

        self._delete_documents(delete_doc_id_dict)
        # gridfsからファイルを消す
        file = File(self.get_db)
        file.fs_delete(delete_file_ref_list)
Beispiel #3
0
Datei: db.py Projekt: ryde/EDMAN
    def delete(self, oid: Union[str, ObjectId], collection: str,
               structure: str) -> bool:
        """
        | ドキュメントを削除する
        | 指定のoidを含む下位のドキュメントを全削除
        | refで親が存在する時は親のchildリストから指定のoidを取り除く

        :param oid:
        :type oid: str or ObjectId
        :param str collection:
        :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:
                result = self.db[collection].delete_one({'_id': oid})
                if result.deleted_count:
                    # 添付データがあればgridfsから削除
                    file = File(self.get_db)
                    file.fs_delete(
                        sum([i for i in self._collect_emb_file_ref(
                            db_result, self.file_ref)], []))
                    return True
                else:
                    sys.exit('指定のドキュメントは削除できませんでした' + str(oid))
            except ValueError as e:
                sys.exit(e)

        elif structure == 'ref':

            try:
                # 親ドキュメントがあれば子要素リストから削除する
                if db_result.get(self.parent):
                    self._delete_reference_from_parent(db_result[self.parent],
                                                       db_result['_id'])

                # 対象のドキュメント以下のドキュメントと関連ファイルを削除する
                self._delete_documents_and_files(db_result, collection)
                return True
            except ValueError as e:
                sys.exit(e)
        else:
            sys.exit('structureはrefまたはembの指定が必要です')
Beispiel #4
0
class TestFile(TestCase):
    @classmethod
    def setUpClass(cls):

        # 設定読み込み
        settings = configparser.ConfigParser()
        settings.read(Path.cwd() / 'ini' / 'test_db.ini')
        cls.test_ini = dict([i for i in settings['DB'].items()])
        cls.test_ini['port'] = int(cls.test_ini['port'])

        # DB作成のため、pymongoから接続
        cls.client = MongoClient(cls.test_ini['host'], cls.test_ini['port'])

        # 接続確認
        try:
            cls.client.admin.command('ismaster')
            cls.db_server_connect = True
            print('Use DB.')
        except errors.ConnectionFailure:
            cls.db_server_connect = False
            print('Do not use DB.')

        if cls.db_server_connect:
            # adminで認証
            cls.client[cls.test_ini['admin_db']].authenticate(
                cls.test_ini['admin_user'], cls.test_ini['admin_password'])
            # DB作成
            cls.client[cls.test_ini['db']].command(
                "createUser",
                cls.test_ini['user'],
                pwd=cls.test_ini['password'],
                roles=[
                    {
                        'role': 'dbOwner',
                        'db': cls.test_ini['db'],
                    },
                ],
            )
            # ユーザ側認証
            cls.client[cls.test_ini['db']].authenticate(
                cls.test_ini['user'], cls.test_ini['password'])
            # edmanのDB接続オブジェクト作成
            cls.con = {
                'host': cls.test_ini['host'],
                'port': cls.test_ini['port'],
                'database': cls.test_ini['db'],
                'auth_database': cls.test_ini['db'],
                'user': cls.test_ini['user'],
                'password': cls.test_ini['password']
            }
            cls.db = DB(cls.con)
            cls.testdb = cls.db.get_db

    @classmethod
    def tearDownClass(cls):
        if cls.db_server_connect:
            # cls.clientはpymongo経由でDB削除
            # cls.testdb.dbはedman側の接続オブジェクト経由でユーザ(自分自身)の削除
            cls.client.drop_database(cls.test_ini['db'])
            # cls.client[cls.admindb].authenticate(cls.adminid, cls.adminpasswd)
            cls.testdb.command("dropUser", cls.test_ini['user'])

    def setUp(self):

        if self.db_server_connect:
            self.file = File(self.db.get_db)
        else:
            self.file = File()
        self.config = Config()

    # def tearDown(self):
    #     pass

    def test_file_gen(self):

        # 正常系
        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)

            expected = []
            for i in range(2):
                gen_file = 'gen_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)

            # ファイル読み込み、テスト
            actual = []
            files = tuple(sorted(p.glob('gen_test*.txt')))
            for idx, f in enumerate(self.file.file_gen(files)):
                filename, filedata = f
                actual.append((filename, filedata.decode()))
            self.assertListEqual(sorted(actual), sorted(expected))

    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)

    def test__file_list_attachment(self):

        # _ed_fileがなかった場合
        doc = {'name': 'NSX', 'ddd': 'aaa'}
        files_oid = [ObjectId(), ObjectId()]
        actual = self.file._file_list_attachment(doc, files_oid)
        expected = {'name': 'NSX', 'ddd': 'aaa', self.config.file: files_oid}
        self.assertDictEqual(expected, actual)

        # _ed_fileがすでに存在する場合
        oid1 = ObjectId()
        oid2 = ObjectId()

        files_oid = [oid1, oid2]
        doc = {'abc': '123', self.config.file: files_oid}
        at_files_oid = [ObjectId(), ObjectId()]
        actual = self.file._file_list_attachment(doc, at_files_oid)

        files_oid2 = [oid1, oid2]
        expected = {'abc': '123', self.config.file: files_oid2 + at_files_oid}

        self.assertDictEqual(actual, expected)

    def test__file_list_replace(self):
        # _ed_fileがある場合
        files_oid = [ObjectId(), ObjectId()]
        doc = {'name': 'NSX', self.config.file: files_oid}
        rep_files_oid = [ObjectId(), ObjectId()]
        actual = self.file._file_list_replace(doc, rep_files_oid)
        expected = {'name': 'NSX', self.config.file: rep_files_oid}
        self.assertDictEqual(expected, actual)

        # 空リストの場合
        doc = {'name': 'NSX', self.config.file: [ObjectId(), ObjectId()]}
        rep_files_oid = []
        actual = self.file._file_list_replace(doc, rep_files_oid)
        expected = {'name': 'NSX'}
        self.assertDictEqual(expected, actual)

        # _ed_fileがない場合(例外になる)
        doc = {'name': 'NSX'}
        rep_files_oid = [ObjectId(), ObjectId()]
        with self.assertRaises(ValueError):
            _ = self.file._file_list_replace(doc, rep_files_oid)

    def test_fs_delete(self):
        if not self.db_server_connect:
            return

        # 正常系
        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)

            for i in range(2):
                gen_file = 'delete_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)

            fs_oids = []
            for i in tuple(sorted(p.glob('delete_test*.txt'))):
                with i.open('rb') as f:
                    self.fs = gridfs.GridFS(self.testdb)
                    fs_oids.append(self.fs.put(f.read(), filename=str(i.name)))

            self.file.fs_delete(fs_oids)
            for i in fs_oids:
                with self.subTest(i=i):
                    self.assertFalse(self.fs.exists(i))

    def test_download(self):
        if not self.db_server_connect:
            return

        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)
            test_vars = {}
            filename_list = []
            for i in range(2):
                name = 'file_dl' + str(i) + '.txt'
                filename_list.append(name)
                save_path = p / name
                with save_path.open('w') as f:
                    test_var = 'test' + str(i)
                    f.write(test_var)
                    test_vars.update({name: test_var})

            # ファイル読み込み、ファイルをgridfsに入れる
            files_oid = []
            self.fs = gridfs.GridFS(self.testdb)
            for filename in sorted(p.glob('file_dl*.txt')):
                with filename.open('rb') as f:
                    file_obj = gzip.compress(f.read(), compresslevel=6)
                    files_oid.append(
                        self.fs.put(file_obj,
                                    filename=filename.name,
                                    compress='gzip'))

            files_list_dic = dict(zip(files_oid, filename_list))

        with tempfile.TemporaryDirectory() as tmp_dl_dir:
            path = Path(tmp_dl_dir)

            # 正常テスト
            expected = {}
            for oid, file_name in files_list_dic.items():
                if self.file.download(oid, path):
                    if path.exists():
                        expected.update({oid: file_name})
            self.assertDictEqual(files_list_dic, expected)

            # files_list_dicファイルの中身が同じかテスト
            for name, txt in test_vars.items():
                dl_path = path / name
                with dl_path.open('rb') as f:
                    raw_data = f.read()
                    dl_data = raw_data.decode()
                    with self.subTest(name=name):
                        self.assertEqual(dl_data, txt)

    def test_get_file_names(self):
        if not self.db_server_connect:
            return

        with tempfile.TemporaryDirectory() as tmp_dir:
            p = Path(tmp_dir)
            filename_list = []
            for i in range(2):
                name = 'file_names' + str(i) + '.txt'
                filename_list.append(name)
                save_path = p / name
                with save_path.open('w') as f:
                    test_var = 'test' + str(i)
                    f.write(test_var)

            # ファイル読み込み、ファイルをgridfsに入れる
            files_oid = []
            self.fs = gridfs.GridFS(self.testdb)
            for filename in sorted(p.glob('file_names*.txt')):
                with filename.open('rb') as f:
                    files_oid.append(
                        self.fs.put(f.read(), filename=filename.name))

            # DocをDBに入れる
            doc = {
                'test1': {
                    'test2': 'name',
                    'test3': {
                        'test4': [{
                            'test5': 'moon',
                            self.config.file: files_oid,
                        }, {
                            'test6': 'star'
                        }]
                    }
                }
            }
            insert_result = self.testdb['structure_emb'].insert_one(doc)

            # 正常系テスト(embのみ.refとembの判断はget_file_ref()で行っているので割愛)
            oid = insert_result.inserted_id
            query = ['test1', 'test3', 'test4', '0']
            actual = self.file.get_file_names('structure_emb', oid, 'emb',
                                              query)
            expected = dict(zip(files_oid, filename_list))
            self.assertDictEqual(actual, expected)

    def test__get_file_ref(self):
        # 正常系(ref)
        expected = [ObjectId(), ObjectId(), ObjectId()]
        doc = {
            'name':
            'test1',
            self.config.file:
            expected,
            self.config.parent:
            DBRef('test0', ObjectId()),
            self.config.child:
            [DBRef('test2', ObjectId()),
             DBRef('test3', ObjectId())]
        }
        structure = 'ref'
        actual = self.file.get_file_ref(doc, structure)
        self.assertListEqual(expected, actual)

        # 正常系(emb)
        expected = [ObjectId(), ObjectId(), ObjectId()]
        doc = {
            'test1': {
                'test2': 'name',
                'test3': {
                    'test4': [{
                        'test5': 'moon',
                        self.config.file: expected,
                    }, {
                        'test6': 'star'
                    }]
                }
            }
        }
        structure = 'emb'
        query = ['test1', 'test3', 'test4', '0']
        actual = self.file.get_file_ref(doc, structure, query)
        self.assertListEqual(expected, actual)

    def test_delete(self):
        if not self.db_server_connect:
            return

        with tempfile.TemporaryDirectory() as tmp_dl_dir:
            p = Path(tmp_dl_dir)
            filename_list = []
            name = 'file_delete.txt'
            filename_list.append(name)
            save_path = p / name
            with save_path.open('w') as f:
                test_var = 'test'
                f.write(test_var)

            # embの添付ファイル削除テスト
            # ファイル読み込み、ファイルをgridfsに入れる
            files_oid = []
            self.fs = gridfs.GridFS(self.testdb)
            for filename in sorted(p.glob('file_delete*.txt')):
                with filename.open('rb') as f:
                    files_oid.append(
                        self.fs.put(f.read(), filename=filename.name))

            # DocをDBに入れる
            doc = {
                'test1': {
                    'test2': 'name',
                    'test3': {
                        'test4': [{
                            'test5': 'moon',
                            self.config.file: files_oid,
                        }, {
                            'test6': 'star'
                        }]
                    }
                }
            }
            insert_result = self.testdb['structure_emb'].insert_one(doc)
            oid = str(insert_result.inserted_id)
            query = ['test1', 'test3', 'test4', '0']

            result = self.file.delete(files_oid[0], 'structure_emb', oid,
                                      'emb', query)
            self.assertTrue(result)
            # ファイルが消えたか検証
            self.assertFalse(self.fs.exists(files_oid[0]))

            # refの添付ファイル削除テスト
            # ファイル読み込み、ファイルをgridfsに入れる
            files_oid = []
            self.fs = gridfs.GridFS(self.testdb)
            for filename in sorted(p.glob('file_delete*.txt')):
                with filename.open('rb') as f:
                    files_oid.append(
                        self.fs.put(f.read(), filename=filename.name))

            # docをDBに入れる
            doc = {
                'name': 'test1',
                self.config.file: files_oid,
                self.config.parent: ObjectId(),
                self.config.child: DBRef('child_col', ObjectId())
            }

            insert_result = self.testdb['structure_ref'].insert_one(doc)
            oid = str(insert_result.inserted_id)

            result = self.file.delete(files_oid[0], 'structure_ref', oid,
                                      'ref')
            self.assertTrue(result)
            # ファイルが消えたか検証
            self.assertFalse(self.fs.exists(files_oid[0]))

    def test__get_emb_files_list(self):

        # 正常系
        file_list = [ObjectId(), ObjectId()]

        doc = {
            "_id":
            ObjectId(),
            "position":
            "top",
            "username":
            "******",
            "bool":
            True,
            "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",
                        self.config.file: file_list,
                    }],
                    "structure_5": {
                        "url": "example.com",
                        "name": "テストURL1",
                        "structure_5": {
                            "url": "example4.com",
                            "name": "テストURL4"
                        }
                    }
                }]
            }]
        }

        query = ['structure_2', '1', 'structure_3_2', '0', 'structure_6', '1']
        actual = self.file._get_emb_files_list(doc, query)

        expected = file_list
        self.assertEqual(expected, actual)
Beispiel #5
0
                    '--query',
                    default=None,
                    help='Ref is ObjectId or Emb is query list strings.')
parser.add_argument('-c',
                    '--compress',
                    action='store_true',
                    help='gzip compress.Default is not compressed.')
args = parser.parse_args()

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

db = DB(con)
file = File(db.get_db)

# 対象oidの所属コレクションを自動的に取得 ※動作が遅い場合は使用しないこと
collection = db.find_collection_from_objectid(args.objectid)

# ドキュメント構造の取得
structure = db.get_structure(collection, args.objectid)

# クエリの変換
query = Action.file_query_eval(args.query, structure)

if file.add_file_reference(collection, args.objectid,
                           Action.files_read(args.path), structure, query,
                           args.compress):
    print('更新しました')
else:
Beispiel #6
0
parser.add_argument('objectid', help='objectid str.')
parser.add_argument('path', help='Download Dir path.')
# クエリは structureがembの時だけ
parser.add_argument('-q',
                    '--query',
                    default=None,
                    help='Ref is ObjectId or Emb is query list strings.')
args = parser.parse_args()

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

db = DB(con)
file = File(db.get_db)

# 対象oidの所属コレクションを自動的に取得 ※動作が遅い場合は使用しないこと
collection = db.find_collection_from_objectid(args.objectid)

# ドキュメント構造の取得
structure = db.get_structure(collection, args.objectid)

# クエリの変換
query = Action.file_query_eval(args.query, structure)

# ファイル名一覧を取得
file_names = file.get_file_names(collection, args.objectid, structure, query)
file_oids = []
# ファイル名一覧を画面表示&file_oid用リスト作成
for idx, (oid, filename) in enumerate(file_names.items()):