# Path: pgcontents/api_utils.py
# def from_api_dirname(api_dirname):
#     """
#     Convert API-style directory name into a db-style directory name.
#     """
#     normalized = normalize_api_path(api_dirname)
#     if normalized == '':
#         return '/'
#     return '/' + normalized + '/'
# 
# def from_api_filename(api_path):
#     """
#     Convert an API-style path into a db-style path.
#     """
#     normalized = normalize_api_path(api_path)
#     assert len(normalized), "Empty path in from_api_filename"
#     return '/' + normalized
# 
# def reads_base64(nb, as_version=NBFORMAT_VERSION):
#     """
#     Read a notebook from base64.
#     """
#     try:
#         return reads(b64decode(nb).decode('utf-8'), as_version=as_version)
#     except Exception as e:
#         raise CorruptedFile(e)
# 
# def split_api_filepath(path):
#     """
#     Split an API file path into directory and name.
#     """
#     parts = path.rsplit('/', 1)
#     if len(parts) == 1:
#         name = parts[0]
#         dirname = '/'
#     else:
#         name = parts[1]
#         dirname = parts[0] + '/'
# 
#     return from_api_dirname(dirname), name
# 
# def to_api_path(db_path):
#     """
#     Convert database path into API-style path.
#     """
#     return db_path.strip('/')
# 
# Path: pgcontents/constants.py
# UNLIMITED = 0
# 
# Path: pgcontents/db_utils.py
# @contextmanager
# def ignore_unique_violation():
#     """
#     Context manager for gobbling unique violations.
# 
#     NOTE: If a unique violation is raised, the existing psql connection will
#     not accept new commands.  This just silences the python-level error.  If
#     you need emit another command after possibly ignoring a unique violation,
#     you should explicitly use savepoints.
#     """
#     try:
#         yield
#     except IntegrityError as error:
#         if not is_unique_violation(error):
#             raise
# 
# def is_unique_violation(error):
#     return error.orig.pgcode == UNIQUE_VIOLATION
# 
# def is_foreign_key_violation(error):
#     return error.orig.pgcode == FOREIGN_KEY_VIOLATION
# 
# def to_dict_no_content(fields, row):
#     """
#     Convert a SQLAlchemy row that does not contain a 'content' field to a dict.
# 
#     If row is None, return None.
# 
#     Raises AssertionError if there is a field named 'content' in ``fields``.
#     """
#     assert(len(fields) == len(row))
# 
#     field_names = list(map(_get_name, fields))
#     assert 'content' not in field_names, "Unexpected content field."
# 
#     return dict(zip(field_names, row))
# 
# def to_dict_with_content(fields, row, decrypt_func):
#     """
#     Convert a SQLAlchemy row that contains a 'content' field to a dict.
# 
#     ``decrypt_func`` will be applied to the ``content`` field of the row.
# 
#     If row is None, return None.
# 
#     Raises AssertionError if there is no field named 'content' in ``fields``.
#     """
#     assert(len(fields) == len(row))
# 
#     field_names = list(map(_get_name, fields))
#     assert 'content' in field_names, "Missing content field."
# 
#     result = dict(zip(field_names, row))
#     result['content'] = decrypt_func(result['content'])
#     return result
# 
# Path: pgcontents/error.py
# class CorruptedFile(Exception):
#     pass
# 
# class DirectoryNotEmpty(Exception):
#     pass
# 
# class FileExists(Exception):
#     pass
# 
# class DirectoryExists(Exception):
#     pass
# 
# class FileTooLarge(Exception):
#     pass
# 
# class NoSuchCheckpoint(Exception):
#     pass
# 
# class NoSuchDirectory(Exception):
#     pass
# 
# class NoSuchFile(Exception):
#     pass
# 
# class RenameRoot(Exception):
#     pass
# 
# Path: pgcontents/schema.py



from sqlalchemy import (
    and_,
    cast,
    desc,
    func,
    null,
    select,
    Unicode,
)
from sqlalchemy.exc import IntegrityError
from .api_utils import (
    from_api_dirname,
    from_api_filename,
    reads_base64,
    split_api_filepath,
    to_api_path,
)
from .constants import UNLIMITED
from .db_utils import (
    ignore_unique_violation,
    is_unique_violation,
    is_foreign_key_violation,
    to_dict_no_content,
    to_dict_with_content,
)
from .error import (
    CorruptedFile,
    DirectoryNotEmpty,
    FileExists,
    DirectoryExists,
    FileTooLarge,
    NoSuchCheckpoint,
    NoSuchDirectory,
    NoSuchFile,
    RenameRoot,
)
from .schema import (
    directories,
    files,
    remote_checkpoints,
    users,
)
        return True
    except NoSuchFile:
        return False


def rename_file(db, user_id, old_api_path, new_api_path):
    """
    Rename a file.
    """
    # Overwriting existing files is disallowed.
    if file_exists(db, user_id, new_api_path):
        raise FileExists(new_api_path)

    new_dir, new_name = split_api_filepath(new_api_path)

    db.execute(
        files.update().where(
            _file_where(user_id, old_api_path),
        ).values(
            name=new_name,
            parent_name=new_dir,
            created_at=func.now(),
        )
    )


def rename_directory(db, user_id, old_api_path, new_api_path):
    """
    Rename a directory.
    """

# Path: pgcontents/api_utils.py
# def from_api_dirname(api_dirname):
#     """
#     Convert API-style directory name into a db-style directory name.
#     """
#     normalized = normalize_api_path(api_dirname)
#     if normalized == '':
#         return '/'
#     return '/' + normalized + '/'
# 
# def from_api_filename(api_path):
#     """
#     Convert an API-style path into a db-style path.
#     """
#     normalized = normalize_api_path(api_path)
#     assert len(normalized), "Empty path in from_api_filename"
#     return '/' + normalized
# 
# def reads_base64(nb, as_version=NBFORMAT_VERSION):
#     """
#     Read a notebook from base64.
#     """
#     try:
#         return reads(b64decode(nb).decode('utf-8'), as_version=as_version)
#     except Exception as e:
#         raise CorruptedFile(e)
# 
# def split_api_filepath(path):
#     """
#     Split an API file path into directory and name.
#     """
#     parts = path.rsplit('/', 1)
#     if len(parts) == 1:
#         name = parts[0]
#         dirname = '/'
#     else:
#         name = parts[1]
#         dirname = parts[0] + '/'
# 
#     return from_api_dirname(dirname), name
# 
# def to_api_path(db_path):
#     """
#     Convert database path into API-style path.
#     """
#     return db_path.strip('/')
# 
# Path: pgcontents/constants.py
# UNLIMITED = 0
# 
# Path: pgcontents/db_utils.py
# @contextmanager
# def ignore_unique_violation():
#     """
#     Context manager for gobbling unique violations.
# 
#     NOTE: If a unique violation is raised, the existing psql connection will
#     not accept new commands.  This just silences the python-level error.  If
#     you need emit another command after possibly ignoring a unique violation,
#     you should explicitly use savepoints.
#     """
#     try:
#         yield
#     except IntegrityError as error:
#         if not is_unique_violation(error):
#             raise
# 
# def is_unique_violation(error):
#     return error.orig.pgcode == UNIQUE_VIOLATION
# 
# def is_foreign_key_violation(error):
#     return error.orig.pgcode == FOREIGN_KEY_VIOLATION
# 
# def to_dict_no_content(fields, row):
#     """
#     Convert a SQLAlchemy row that does not contain a 'content' field to a dict.
# 
#     If row is None, return None.
# 
#     Raises AssertionError if there is a field named 'content' in ``fields``.
#     """
#     assert(len(fields) == len(row))
# 
#     field_names = list(map(_get_name, fields))
#     assert 'content' not in field_names, "Unexpected content field."
# 
#     return dict(zip(field_names, row))
# 
# def to_dict_with_content(fields, row, decrypt_func):
#     """
#     Convert a SQLAlchemy row that contains a 'content' field to a dict.
# 
#     ``decrypt_func`` will be applied to the ``content`` field of the row.
# 
#     If row is None, return None.
# 
#     Raises AssertionError if there is no field named 'content' in ``fields``.
#     """
#     assert(len(fields) == len(row))
# 
#     field_names = list(map(_get_name, fields))
#     assert 'content' in field_names, "Missing content field."
# 
#     result = dict(zip(field_names, row))
#     result['content'] = decrypt_func(result['content'])
#     return result
# 
# Path: pgcontents/error.py
# class CorruptedFile(Exception):
#     pass
# 
# class DirectoryNotEmpty(Exception):
#     pass
# 
# class FileExists(Exception):
#     pass
# 
# class DirectoryExists(Exception):
#     pass
# 
# class FileTooLarge(Exception):
#     pass
# 
# class NoSuchCheckpoint(Exception):
#     pass
# 
# class NoSuchDirectory(Exception):
#     pass
# 
# class NoSuchFile(Exception):
#     pass
# 
# class RenameRoot(Exception):
#     pass
# 
# Path: pgcontents/schema.py



# Path: pgcontents/query.py
from sqlalchemy import (
    and_,
    cast,
    desc,
    func,
    null,
    select,
    Unicode,
)
from sqlalchemy.exc import IntegrityError
from .api_utils import (
    from_api_dirname,
    from_api_filename,
    reads_base64,
    split_api_filepath,
    to_api_path,
)
from .constants import UNLIMITED
from .db_utils import (
    ignore_unique_violation,
    is_unique_violation,
    is_foreign_key_violation,
    to_dict_no_content,
    to_dict_with_content,
)
from .error import (
    CorruptedFile,
    DirectoryNotEmpty,
    FileExists,
    DirectoryExists,
    FileTooLarge,
    NoSuchCheckpoint,
    NoSuchDirectory,
    NoSuchFile,
    RenameRoot,
)
from .schema import (
    directories,
    files,
    remote_checkpoints,
    users,
)

        return True
    except NoSuchFile:
        return False


def rename_file(db, user_id, old_api_path, new_api_path):
    """
    Rename a file.
    """
    # Overwriting existing files is disallowed.
    if file_exists(db, user_id, new_api_path):
        raise FileExists(new_api_path)

    new_dir, new_name = split_api_filepath(new_api_path)

    db.execute(
        files.update().where(
            _file_where(user_id, old_api_path),
        ).values(
            name=new_name,
            parent_name=new_dir,
            created_at=func.now(),
        )
    )


def rename_directory(db, user_id, old_api_path, new_api_path):
    """
    Rename a directory.
    """

    old_db_path = from_api_dirname(old_api_path)