# Path: g_sorcery/exceptions.py
# class DBLayoutError(GSorceryError):
#     pass
# 
# class DBStructureError(DBError):
#     pass
# 
# class FileJSONError(GSorceryError):
#     pass
# 
# class IntegrityError(DBError):
#     pass
# 
# Path: g_sorcery/fileutils.py
# class FileJSON(FileJSONData):
#     """
#     Class for JSON files. Supports custom JSON serialization
#     provided by g_sorcery.serialization.
#     """
# 
#     def read_content(self):
#         """
#         Read JSON file.
#         """
#         content = {}
#         with open(self.path, 'r') as f:
#             content = json.load(f, object_hook=deserializeHook)
#         return content
# 
#     def write_content(self, content):
#         """
#         Write JSON file.
#         """
#         with open(self.path, 'w') as f:
#             json.dump(content, f, indent=2, sort_keys=True, cls=JSONSerializer)
# 
# def hash_file(name, hasher, blocksize=65536):
#     """
#     Get a file hash.
# 
#     Args:
#         name: file name.
#         hasher: Hasher.
#         blocksize: Blocksize.
# 
#     Returns:
#         Hash value.
#     """
#     with open(name, 'rb') as f:
#         buf = f.read(blocksize)
#         while len(buf) > 0:
#             hasher.update(buf)
#             buf = f.read(blocksize)
#     return hasher.hexdigest()


import hashlib
import os
import shutil
from .exceptions import DBLayoutError, DBStructureError, FileJSONError, IntegrityError
from .fileutils import FileJSON, hash_file
    from .file_bson.file_bson import FileBSON
class Metadata(FileJSON):
    """
    Metadata file.
    """
    def __init__(self, directory):
        super(Metadata, self).__init__(os.path.abspath(directory),
                                       file_name(METADATA_FILE_NAME),
                                       ['db_version', 'layout_version', 'category_format'])

    def read(self):
        """
        Read metadata file.

        If file doesn't exist, we have a legacy DB
        with DB layout v. 0. Fill metadata appropriately.
        """
        if not os.path.exists(self.directory):
            os.makedirs(self.directory)
        content = {}
        if not os.path.isfile(self.path):
            content = {'db_version': 0, 'layout_version': 0, 'category_format': JSON_FILE_SUFFIX}
        else:
            content = self.read_content()
            for key in self.mandatories:
                if not key in content:
                    raise FileJSONError('lack of mandatory key: ' + key)

        return content



# Path: g_sorcery/exceptions.py
# class DBLayoutError(GSorceryError):
#     pass
# 
# class DBStructureError(DBError):
#     pass
# 
# class FileJSONError(GSorceryError):
#     pass
# 
# class IntegrityError(DBError):
#     pass
# 
# Path: g_sorcery/fileutils.py
# class FileJSON(FileJSONData):
#     """
#     Class for JSON files. Supports custom JSON serialization
#     provided by g_sorcery.serialization.
#     """
# 
#     def read_content(self):
#         """
#         Read JSON file.
#         """
#         content = {}
#         with open(self.path, 'r') as f:
#             content = json.load(f, object_hook=deserializeHook)
#         return content
# 
#     def write_content(self, content):
#         """
#         Write JSON file.
#         """
#         with open(self.path, 'w') as f:
#             json.dump(content, f, indent=2, sort_keys=True, cls=JSONSerializer)
# 
# def hash_file(name, hasher, blocksize=65536):
#     """
#     Get a file hash.
# 
#     Args:
#         name: file name.
#         hasher: Hasher.
#         blocksize: Blocksize.
# 
#     Returns:
#         Hash value.
#     """
#     with open(name, 'rb') as f:
#         buf = f.read(blocksize)
#         while len(buf) > 0:
#             hasher.update(buf)
#             buf = f.read(blocksize)
#     return hasher.hexdigest()


# Path: g_sorcery/db_layout.py
import hashlib
import os
import shutil
from .exceptions import DBLayoutError, DBStructureError, FileJSONError, IntegrityError
from .fileutils import FileJSON, hash_file
    from .file_bson.file_bson import FileBSON

class Metadata(FileJSON):
    """
    Metadata file.
    """
    def __init__(self, directory):
        super(Metadata, self).__init__(os.path.abspath(directory),
                                       file_name(METADATA_FILE_NAME),
                                       ['db_version', 'layout_version', 'category_format'])

    def read(self):
        """
        Read metadata file.

        If file doesn't exist, we have a legacy DB
        with DB layout v. 0. Fill metadata appropriately.
        """
        if not os.path.exists(self.directory):
            os.makedirs(self.directory)
        content = {}
        if not os.path.isfile(self.path):
            content = {'db_version': 0, 'layout_version': 0, 'category_format': JSON_FILE_SUFFIX}
        else:
            content = self.read_content()
            for key in self.mandatories:
                if not key in content:
                    raise FileJSONError('lack of mandatory key: ' + key)

        return content



class Categories(FileJSON):