def read_schema(path: util.PathLike) -> Schema: """ Instantiate schema dict from a schema file given by *path*. If *path* is a directory, use the relations file under *path*. If *path* is a file, use it directly as the schema's path. Otherwise raise a :exc:`TSDBSchemaError`. """ path = Path(path).expanduser() if path.is_dir(): path = path.joinpath(SCHEMA_FILENAME) if not path.is_file(): raise TSDBSchemaError(f'no valid schema file at {path!s}') return _parse_schema(path.read_text())
def write_database(db: Database, path: util.PathLike, names: Iterable[str] = None, schema: SchemaLike = None, gzip: bool = False, encoding: str = 'utf-8') -> None: """ Write TSDB database *db* to *path*. If *path* is an existing file (not a directory), a :class:`TSDBError` is raised. If *path* is an existing directory, the files for all relations in the destination schema will be cleared. Every relation name in *names* must exist in the destination schema. If *schema* is given (even if it is the same as for *db*), every record will be remade (using :func:`make_record`) using the schema, and columns may be dropped or `None` values inserted as necessary, but no more sophisticated changes will be made. .. warning:: If *path* points to an existing directory, all relation files defined by the schema will be overwritten or deleted. Args: db: Database containing data to write path: the path to the destination database directory names: list of names of relations to write; if `None` use all relations in the destination schema schema: the destination database schema; if `None` use the schema of *db* gzip: if `True`, compress all non-empty files; if `False`, do not compress encoding: character encoding for the database files """ path = Path(path).expanduser() if path.is_file(): raise TSDBError(f'not a directory: {path!s}') remake_records = schema is not None if schema is None: schema = db.schema elif isinstance(schema, (str, Path)): schema = read_schema(schema) if names is None: names = list(schema) # Prepare destination directory path.mkdir(exist_ok=True) write_schema(path, schema) for name in names: fields = schema[name] relation: Iterable[Record] = [] if name in db.schema: try: relation = db[name] except (TSDBError, KeyError): pass if remake_records: relation = _remake_records(relation, db.schema[name], fields) write(path, name, relation, fields, append=False, gzip=gzip, encoding=encoding) # only delete other files at the end in case db.path == path _cleanup_files(path, set(schema).difference(names))