# Path: jacquard/commands.py
# class BaseCommand(metaclass=abc.ABCMeta):
#     """
#     Abstract base class for subcommands.
# 
#     Subclasses *must* override `handle` and *may* also provide a `help` string
#     and/or override `add_arguments`.
#     """
# 
#     def add_arguments(self, parser):
#         """Add argument definitions to a given argparse `ArgumentParser`."""
#         pass
# 
#     @abc.abstractmethod
#     def handle(self, config, options):
#         """
#         Run command.
# 
#         `config` is the system configuration from `jacquard.config` and
#         `options` is a `Namespace`-like object of command-line options,
#         generally defined from `add_arguments` with a few standard options
#         such as `verbose` thrown in for good measure.
#         """
#         raise NotImplementedError
# 
# class CommandError(Exception):
#     """
#     Generic, user-visible error.
# 
#     Where this is raised with a message, the message will generally be printed
#     to standard error without a backtrace.
#     """
# 
#     pass
# 
# Path: jacquard/storage/utils.py
# def retrying(fn):
#     """Decorator: reissues the function if it raises Retry."""
#     logger = logging.getLogger("jacquard.storage.retrying")
# 
#     @functools.wraps(fn)
#     def wrapper(*args, **kwargs):
#         while True:
#             try:
#                 return fn(*args, **kwargs)
#             except Retry:
#                 callable_name = getattr(fn, "__name__", "anonymous function")
#                 logger.debug("Retry issued from %s, reissuing", callable_name)
# 
#     return wrapper
# 
# def copy_data(from_engine, to_engine, flush=False):
#     """Copy all keys between two storage engines."""
#     with from_engine.transaction(read_only=True) as src:
#         with to_engine.transaction() as dst:
#             if flush:
#                 dst.clear()
#             dst.update(src)
# 
# def open_engine(config, engine, url):
#     """
#     Open and connect to a given engine and URL.
# 
#     This looks up the backend through the entry points mechanism, and is
#     pluggable by adding `StorageEngine` subclasses to the entry points
#     group `jacquard.storage_engines`.
#     """
#     cls = plug("storage_engines", engine, config=config)()
#     return cls(url)


import pprint
from jacquard.commands import BaseCommand, CommandError
from jacquard.storage.utils import retrying, copy_data, open_engine
"""Command-line utilities for storage subsystem."""




class StorageDump(BaseCommand):
    """
    Dump everything in the store to stdout.

    This is a debugging command, mainly for developer use.
    """

    plumbing = True
    help = "dump all objects in storage"

    def handle(self, config, options):
        """Run command."""
        with config.storage.transaction(read_only=True) as store:
            for key, value in store.items():
                print(key)
                print("=" * len(key))
                pprint.pprint(value)
                print()



# Path: jacquard/commands.py
# class BaseCommand(metaclass=abc.ABCMeta):
#     """
#     Abstract base class for subcommands.
# 
#     Subclasses *must* override `handle` and *may* also provide a `help` string
#     and/or override `add_arguments`.
#     """
# 
#     def add_arguments(self, parser):
#         """Add argument definitions to a given argparse `ArgumentParser`."""
#         pass
# 
#     @abc.abstractmethod
#     def handle(self, config, options):
#         """
#         Run command.
# 
#         `config` is the system configuration from `jacquard.config` and
#         `options` is a `Namespace`-like object of command-line options,
#         generally defined from `add_arguments` with a few standard options
#         such as `verbose` thrown in for good measure.
#         """
#         raise NotImplementedError
# 
# class CommandError(Exception):
#     """
#     Generic, user-visible error.
# 
#     Where this is raised with a message, the message will generally be printed
#     to standard error without a backtrace.
#     """
# 
#     pass
# 
# Path: jacquard/storage/utils.py
# def retrying(fn):
#     """Decorator: reissues the function if it raises Retry."""
#     logger = logging.getLogger("jacquard.storage.retrying")
# 
#     @functools.wraps(fn)
#     def wrapper(*args, **kwargs):
#         while True:
#             try:
#                 return fn(*args, **kwargs)
#             except Retry:
#                 callable_name = getattr(fn, "__name__", "anonymous function")
#                 logger.debug("Retry issued from %s, reissuing", callable_name)
# 
#     return wrapper
# 
# def copy_data(from_engine, to_engine, flush=False):
#     """Copy all keys between two storage engines."""
#     with from_engine.transaction(read_only=True) as src:
#         with to_engine.transaction() as dst:
#             if flush:
#                 dst.clear()
#             dst.update(src)
# 
# def open_engine(config, engine, url):
#     """
#     Open and connect to a given engine and URL.
# 
#     This looks up the backend through the entry points mechanism, and is
#     pluggable by adding `StorageEngine` subclasses to the entry points
#     group `jacquard.storage_engines`.
#     """
#     cls = plug("storage_engines", engine, config=config)()
#     return cls(url)


# Path: jacquard/storage/commands.py
import pprint
from jacquard.commands import BaseCommand, CommandError
from jacquard.storage.utils import retrying, copy_data, open_engine

"""Command-line utilities for storage subsystem."""




class StorageDump(BaseCommand):
    """
    Dump everything in the store to stdout.

    This is a debugging command, mainly for developer use.
    """

    plumbing = True
    help = "dump all objects in storage"

    def handle(self, config, options):
        """Run command."""
        with config.storage.transaction(read_only=True) as store:
            for key, value in store.items():
                print(key)
                print("=" * len(key))
                pprint.pprint(value)
                print()



class StorageImport(BaseCommand):