Browse Source

Docstring conversion #1.

* lsup-admin
* ldpr
* migrator
Stefano Cossu 6 years ago
parent
commit
0c244601f7
3 changed files with 136 additions and 143 deletions
  1. 10 9
      lakesuperior/migrator.py
  2. 114 110
      lakesuperior/model/ldpr.py
  3. 12 24
      lsup-admin

+ 10 - 9
lakesuperior/migrator.py

@@ -21,9 +21,9 @@ logger = logging.getLogger(__name__)
 
 
 class StoreWrapper(ContextDecorator):
-    '''
+    """
     Open and close a store.
-    '''
+    """
     def __init__(self, store):
         self.store = store
 
@@ -74,17 +74,17 @@ class Migrator:
         """
         Set up base paths and clean up existing directories.
 
-        :param src: (URIRef) Webroot of source repository. This must
+        :param rdflib.URIRef src: Webroot of source repository. This must
         correspond to the LDP root node (for Fedora it can be e.g.
         ``http://localhost:8080fcrepo/rest/``) and is used to determine if URIs
         retrieved are managed by this repository.
-        :param dest: (str) Destination repository path. If the location exists
+        :param str dest: Destination repository path. If the location exists
         it must be a writable directory. It will be deleted and recreated. If
         it does not exist, it will be created along with its parents if
         missing.
-        :param binary_handling: (string) One of ``include``, ``truncate`` or
+        :param str binary_handling: One of ``include``, ``truncate`` or
         ``split``.
-        :param compact_uris: (bool) NOT IMPLEMENTED. Whether the process should
+        :param bool compact_uris: NOT IMPLEMENTED. Whether the process should
         attempt to compact URIs generated with broken up path segments. If the
         UID matches a pattern such as `/12/34/56/123456...` it is converted to
         `/123456...`. This would remove a lot of cruft caused by the pairtree
@@ -112,7 +112,7 @@ class Migrator:
                 as config_file:
             config_file.write(yaml.dump(orig_config['application']))
 
-        env.config, _ = parse_config(self.config_dir)
+        env.config = parse_config(self.config_dir)[0]
         env.app_globals = AppGlobals(env.config)
 
         self.rdfly = env.app_globals.rdfly
@@ -136,7 +136,8 @@ class Migrator:
         This method creates a fully functional and configured LAKEsuperior
         data set contained in a folder from an LDP repository.
 
-        :param tuple|list start_pts: List of starting points to retrieve
+        :param start_pts: List of starting points to retrieve
+        :type start_pts: tuple or list 
         resources from. It would typically be the repository root in case of a
         full dump or one or more resources in the repository for a partial one.
         :param str listf_ile: path to a local file containing a list of URIs,
@@ -177,7 +178,7 @@ class Migrator:
         This method recurses into itself each time a reference to a resource
         managed by the repository is encountered.
 
-        @param uid (string) The path relative to the source server webroot
+        :param str uid: The path relative to the source server webroot
         pointing to the resource to crawl, effectively the resource UID.
         """
         ibase = str(nsc['fcres'])

+ 114 - 110
lakesuperior/model/ldpr.py

@@ -28,7 +28,7 @@ logger = logging.getLogger(__name__)
 
 
 class Ldpr(metaclass=ABCMeta):
-    '''LDPR (LDP Resource).
+    """LDPR (LDP Resource).
 
     Definition: https://www.w3.org/TR/ldp/#ldpr-resource
 
@@ -51,7 +51,7 @@ class Ldpr(metaclass=ABCMeta):
 
     The data passed to the store layout for processing should be in a graph.
     All conversion from request payload strings is done here.
-    '''
+    """
 
     EMBED_CHILD_RES_URI = nsc['fcrepo'].EmbedResources
     FCREPO_PTREE_TYPE = nsc['fcrepo'].Pairtree
@@ -95,10 +95,10 @@ class Ldpr(metaclass=ABCMeta):
 
     # Predicates to remove when a resource is replaced.
     delete_preds_on_replace = {
-        nsc['ebucore'].hasMimeType, 
+        nsc['ebucore'].hasMimeType,
         nsc['fcrepo'].lastModified,
         nsc['fcrepo'].lastModifiedBy,
-        nsc['premis'].hasSize, 
+        nsc['premis'].hasSize,
         nsc['premis'].hasMessageDigest,
     }
 
@@ -106,18 +106,18 @@ class Ldpr(metaclass=ABCMeta):
     ## MAGIC METHODS ##
 
     def __init__(self, uid, repr_opts={}, provided_imr=None, **kwargs):
-        '''Instantiate an in-memory LDP resource that can be loaded from and
+        """Instantiate an in-memory LDP resource that can be loaded from and
         persisted to storage.
 
-        @param uid (string) uid of the resource. If None (must be explicitly
+        :param str uid: uid of the resource. If None (must be explicitly
         set) it refers to the root node. It can also be the full URI or URN,
         in which case it will be converted.
-        @param repr_opts (dict) Options used to retrieve the IMR. See
+        :param dict repr_opts: Options used to retrieve the IMR. See
         `parse_rfc7240` for format details.
-        @Param provd_rdf (string) RDF data provided by the client in
+        :param str provd_rdf: RDF data provided by the client in
         operations such as `PUT` or `POST`, serialized as a string. This sets
         the `provided_imr` property.
-        '''
+        """
         self.uid = (
             rdfly.uri_to_uid(uid) if isinstance(uid, URIRef) else uid)
         self.uri = nsc['fcres'][uid]
@@ -132,12 +132,12 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def rsrc(self):
-        '''
+        """
         The RDFLib resource representing this LDPR. This is a live
         representation of the stored data if present.
 
         @return rdflib.resource.Resource
-        '''
+        """
         if not hasattr(self, '_rsrc'):
             self._rsrc = rdfly.ds.resource(self.uri)
 
@@ -146,14 +146,14 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def imr(self):
-        '''
+        """
         Extract an in-memory resource from the graph store.
 
         If the resource is not stored (yet), a `ResourceNotExistsError` is
         raised.
 
         @return rdflib.resource.Resource
-        '''
+        """
         if not hasattr(self, '_imr'):
             if hasattr(self, '_imr_options'):
                 logger.debug(
@@ -171,12 +171,12 @@ class Ldpr(metaclass=ABCMeta):
 
     @imr.setter
     def imr(self, v):
-        '''
+        """
         Replace in-memory buffered resource.
 
-        @param v (set | rdflib.Graph) New set of triples to populate the IMR
-        with.
-        '''
+        :param v: New set of triples to populate the IMR with.
+        :type v: set or rdflib.Graph
+        """
         if isinstance(v, Resource):
             v = v.graph
         self._imr = Resource(Graph(), self.uri)
@@ -186,17 +186,17 @@ class Ldpr(metaclass=ABCMeta):
 
     @imr.deleter
     def imr(self):
-        '''
+        """
         Delete in-memory buffered resource.
-        '''
+        """
         delattr(self, '_imr')
 
 
     @property
     def metadata(self):
-        '''
+        """
         Get resource metadata.
-        '''
+        """
         if not hasattr(self, '_metadata'):
             if hasattr(self, '_imr'):
                 logger.info('Metadata is IMR.')
@@ -211,9 +211,9 @@ class Ldpr(metaclass=ABCMeta):
 
     @metadata.setter
     def metadata(self, rsrc):
-        '''
+        """
         Set resource metadata.
-        '''
+        """
         if not isinstance(rsrc, Resource):
             raise TypeError('Provided metadata is not a Resource object.')
         self._metadata = rsrc
@@ -221,9 +221,9 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def out_graph(self):
-        '''
+        """
         Retun a graph of the resource's IMR formatted for output.
-        '''
+        """
         out_gr = Graph(identifier=self.uri)
 
         for t in self.imr.graph:
@@ -235,8 +235,8 @@ class Ldpr(metaclass=ABCMeta):
                 }
             ) and (
                 # Only include server managed triples if requested.
-                self._imr_options.get('incl_srv_mgd', True)
-                or not self._is_trp_managed(t)
+                self._imr_options.get('incl_srv_mgd', True) or
+                not self._is_trp_managed(t)
             ):
                 out_gr.add(t)
 
@@ -245,9 +245,9 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def version_info(self):
-        '''
+        """
         Return version metadata (`fcr:versions`).
-        '''
+        """
         if not hasattr(self, '_version_info'):
             try:
                 #@ TODO get_version_info should return a graph.
@@ -260,12 +260,12 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def version_uids(self):
-        '''
+        """
         Return a generator of version UIDs (relative to their parent resource).
-        '''
+        """
         gen = self.version_info[
-                self.uri :
-                nsc['fcrepo'].hasVersion / nsc['fcrepo'].hasVersionLabel :]
+            self.uri:
+            nsc['fcrepo'].hasVersion / nsc['fcrepo'].hasVersionLabel:]
 
         return {str(uid) for uid in gen}
 
@@ -283,10 +283,10 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def types(self):
-        '''All RDF types.
+        """All RDF types.
 
         @return set(rdflib.term.URIRef)
-        '''
+        """
         if not hasattr(self, '_types'):
             if len(self.metadata.graph):
                 metadata = self.metadata
@@ -303,10 +303,10 @@ class Ldpr(metaclass=ABCMeta):
 
     @property
     def ldp_types(self):
-        '''The LDP types.
+        """The LDP types.
 
         @return set(rdflib.term.URIRef)
-        '''
+        """
         if not hasattr(self, '_ldp_types'):
             self._ldp_types = {t for t in self.types if nsc['ldp'] in t}
 
@@ -316,9 +316,9 @@ class Ldpr(metaclass=ABCMeta):
     ## LDP METHODS ##
 
     def head(self):
-        '''
+        """
         Return values for the headers.
-        '''
+        """
         out_headers = defaultdict(list)
 
         digest = self.metadata.value(nsc['premis'].hasMessageDigest)
@@ -339,19 +339,19 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def get_version(self, ver_uid, **kwargs):
-        '''
+        """
         Get a version by label.
-        '''
+        """
         return rdfly.extract_imr(self.uid, ver_uid, **kwargs).graph
 
 
     def create_or_replace(self, create_only=False):
-        '''
+        """
         Create or update a resource. PUT and POST methods, which are almost
         identical, are wrappers for this method.
 
-        @param create_only (boolean) Whether this is a create-only operation.
-        '''
+        :param boolean create_only: Whether this is a create-only operation.
+        """
         create = create_only or not self.is_stored
 
         ev_type = RES_CREATED if create else RES_UPDATED
@@ -367,8 +367,8 @@ class Ldpr(metaclass=ABCMeta):
         remove_trp = {
             (self.uri, pred, None) for pred in self.delete_preds_on_replace}
         add_trp = (
-                set(self.provided_imr.graph)
-                | self._containment_rel(create))
+            set(self.provided_imr.graph) |
+            self._containment_rel(create))
 
         self._modify_rsrc(ev_type, remove_trp, add_trp)
         new_gr = Graph()
@@ -381,14 +381,14 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def bury_rsrc(self, inbound, tstone_pointer=None):
-        '''
+        """
         Delete a single resource and create a tombstone.
 
-        @param inbound (boolean) Whether to delete the inbound relationships.
-        @param tstone_pointer (URIRef) If set to a URN, this creates a pointer
+        :param boolean inbound: Whether to delete the inbound relationships.
+        :param URIRef tstone_pointer: If set to a URN, this creates a pointer
         to the tombstone of the resource that used to contain the deleted
         resource. Otherwise the deleted resource becomes a tombstone.
-        '''
+        """
         logger.info('Burying resource {}'.format(self.uid))
         # Create a backup snapshot for resurrection purposes.
         self.create_rsrc_snapshot(uuid4())
@@ -420,9 +420,9 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def forget_rsrc(self, inbound=True):
-        '''
+        """
         Remove all traces of a resource and versions.
-        '''
+        """
         logger.info('Purging resource {}'.format(self.uid))
         refint = env.config['store']['ldp_rs']['referential_integrity']
         inbound = True if refint else inbound
@@ -433,9 +433,9 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def create_rsrc_snapshot(self, ver_uid):
-        '''
+        """
         Perform version creation and return the version UID.
-        '''
+        """
         # Create version resource from copying the current state.
         logger.info(
             'Creating version snapshot {} for resource {}.'.format(
@@ -479,21 +479,21 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def resurrect_rsrc(self):
-        '''
+        """
         Resurrect a resource from a tombstone.
 
         @EXPERIMENTAL
-        '''
+        """
         tstone_trp = set(rdfly.extract_imr(self.uid, strict=False).graph)
 
-        ver_rsp = self.version_info.graph.query('''
+        ver_rsp = self.version_info.graph.query("""
         SELECT ?uid {
           ?latest fcrepo:hasVersionLabel ?uid ;
             fcrepo:created ?ts .
         }
         ORDER BY DESC(?ts)
         LIMIT 1
-        ''')
+        """)
         ver_uid = str(ver_rsp.bindings[0]['uid'])
         ver_trp = set(rdfly.get_metadata(self.uid, ver_uid).graph)
 
@@ -504,9 +504,9 @@ class Ldpr(metaclass=ABCMeta):
             }:
                 laz_gr.add((self.uri, t[1], t[2]))
         laz_gr.add((self.uri, RDF.type, nsc['fcrepo'].Resource))
-        if nsc['ldp'].NonRdfSource in laz_gr[: RDF.type :]:
+        if nsc['ldp'].NonRdfSource in laz_gr[:RDF.type:]:
             laz_gr.add((self.uri, RDF.type, nsc['fcrepo'].Binary))
-        elif nsc['ldp'].Container in laz_gr[: RDF.type :]:
+        elif nsc['ldp'].Container in laz_gr[:RDF.type:]:
             laz_gr.add((self.uri, RDF.type, nsc['fcrepo'].Container))
 
         laz_set = set(laz_gr) | self._containment_rel()
@@ -517,16 +517,16 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def create_version(self, ver_uid=None):
-        '''
+        """
         Create a new version of the resource.
 
         NOTE: This creates an event only for the resource being updated (due
         to the added `hasVersion` triple and possibly to the `hasVersions` one)
         but not for the version being created.
 
-        @param ver_uid Version ver_uid. If already existing, an exception is
+        :param  ver_uid: Version ver_uid. If already existing, an exception is
         raised.
-        '''
+        """
         if not ver_uid or ver_uid in self.version_uids:
             ver_uid = str(uuid4())
 
@@ -534,13 +534,13 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def revert_to_version(self, ver_uid, backup=True):
-        '''
+        """
         Revert to a previous version.
 
-        @param ver_uid (string) Version UID.
-        @param backup (boolean) Whether to create a backup snapshot. Default is
+        :param str ver_uid: Version UID.
+        :param boolean backup: Whether to create a backup snapshot. Default is
         true.
-        '''
+        """
         # Create a backup snapshot.
         if backup:
             self.create_version()
@@ -561,47 +561,50 @@ class Ldpr(metaclass=ABCMeta):
     ## PROTECTED METHODS ##
 
     def _is_trp_managed(self, t):
-        '''
+        """
         Whether a triple is server-managed.
 
-        @return boolean
-        '''
+        :param tuple t: Triple as a 3-tuple of terms.
+
+        :rtype: boolean
+        """
         return t[1] in srv_mgd_predicates or (
             t[1] == RDF.type and t[2] in srv_mgd_types)
 
 
     def _modify_rsrc(
             self, ev_type, remove_trp=set(), add_trp=set()):
-        '''
+        """
         Low-level method to modify a graph for a single resource.
 
         This is a crucial point for messaging. Any write operation on the RDF
         store that needs to be notified should be performed by invoking this
         method.
 
-        @param ev_type (string|None) The type of event (create, update,
+        :param ev_type: The type of event (create, update,
         delete) or None. In the latter case, no notification is sent.
-        @param remove_trp (set) Triples to be removed.
-        @param add_trp (set) Triples to be added.
-        '''
+        :type ev_type: str or None
+        :param set remove_trp: Triples to be removed.
+        :param set add_trp: Triples to be added.
+        """
         rdfly.modify_rsrc(self.uid, remove_trp, add_trp)
 
         if (
-                ev_type is not None
-                and env.config['application'].get('messaging')):
+                ev_type is not None and
+                env.config['application'].get('messaging')):
             logger.debug('Enqueuing message for {}'.format(self.uid))
             self._enqueue_msg(ev_type, remove_trp, add_trp)
 
 
     def _enqueue_msg(self, ev_type, remove_trp=None, add_trp=None):
-        '''
+        """
         Compose a message about a resource change.
 
         The message is enqueued for asynchronous processing.
 
-        @param ev_type (string) The event type. See global constants.
-        @param remove_trp (set) Triples removed. Only used if the 
-        '''
+        :param str ev_type: The event type. See global constants.
+        :param set remove_trp: Triples removed. Only used if the
+        """
         try:
             rsrc_type = tuple(str(t) for t in self.types)
             actor = self.metadata.value(nsc['fcrepo'].createdBy)
@@ -639,11 +642,11 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _check_mgd_terms(self, gr):
-        '''
+        """
         Check whether server-managed terms are in a RDF payload.
 
-        @param gr (rdflib.Graph) The graph to validate.
-        '''
+        :param rdflib.Graph gr: The graph to validate.
+        """
         offending_subjects = set(gr.subjects()) & srv_mgd_subjects
         if offending_subjects:
             if self.handling == 'strict':
@@ -680,11 +683,11 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _add_srv_mgd_triples(self, create=False):
-        '''
+        """
         Add server-managed triples to a provided IMR.
 
-        @param create (boolean) Whether the resource is being created.
-        '''
+        :param  create: Whether the resource is being created.
+        """
         # Base LDP types.
         for t in self.base_types:
             self.provided_imr.add(RDF.type, t)
@@ -712,7 +715,7 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _containment_rel(self, create):
-        '''Find the closest parent in the path indicated by the uid and
+        """Find the closest parent in the path indicated by the uid and
         establish a containment triple.
 
         Check the path-wise parent of the new resource. If it exists, add the
@@ -728,9 +731,9 @@ class Ldpr(metaclass=ABCMeta):
         - If fcres:/e is being created, the root node becomes container of
           fcres:/e.
 
-        @param create (bool) Whether the resource is being created. If false,
+        :param bool create: Whether the resource is being created. If false,
         the parent container is not updated.
-        '''
+        """
         from lakesuperior.model.ldp_factory import LdpFactory
 
         if '/' in self.uid.lstrip('/'):
@@ -754,13 +757,13 @@ class Ldpr(metaclass=ABCMeta):
             parent_uid = ROOT_UID
 
         parent_rsrc = LdpFactory.from_stored(
-            parent_uid, repr_opts={'incl_children' : False}, handling='none')
+            parent_uid, repr_opts={'incl_children': False}, handling='none')
 
         # Only update parent if the resource is new.
         if create:
             add_gr = Graph()
             add_gr.add(
-                    (nsc['fcres'][parent_uid], nsc['ldp'].contains, self.uri))
+                (nsc['fcres'][parent_uid], nsc['ldp'].contains, self.uri))
             parent_rsrc._modify_rsrc(RES_UPDATED, add_trp=add_gr)
 
         # Direct or indirect container relationship.
@@ -768,13 +771,13 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _dedup_deltas(self, remove_gr, add_gr):
-        '''
+        """
         Remove duplicate triples from add and remove delta graphs, which would
         otherwise contain unnecessary statements that annul each other.
 
         @return tuple 2 "clean" sets of respectively remove statements and
         add statements.
-        '''
+        """
         return (
             remove_gr - add_gr,
             add_gr - remove_gr
@@ -782,11 +785,11 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _add_ldp_dc_ic_rel(self, cont_rsrc):
-        '''
+        """
         Add relationship triples from a parent direct or indirect container.
 
-        @param cont_rsrc (rdflib.resource.Resouce)  The container resource.
-        '''
+        :param rdflib.resource.Resouce cont_rsrc:  The container resource.
+        """
         cont_p = set(cont_rsrc.metadata.graph.predicates())
 
         logger.info('Checking direct or indirect containment.')
@@ -807,8 +810,9 @@ class Ldpr(metaclass=ABCMeta):
                 o = self.uri
 
             elif (
-                    cont_rsrc.metadata[RDF.type: nsc['ldp'].IndirectContainer]
-                    and self.INS_CNT_REL_URI in cont_p):
+                    cont_rsrc.metadata[
+                        RDF.type: nsc['ldp'].IndirectContainer] and
+                    self.INS_CNT_REL_URI in cont_p):
                 logger.info('Parent is an indirect container.')
                 cont_rel_uri = cont_rsrc.metadata.value(
                     self.INS_CNT_REL_URI).identifier
@@ -823,21 +827,20 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def sparql_update(self, update_str):
-        '''
+        """
         Apply a SPARQL update to a resource.
 
-        @param update_str (string) SPARQL-Update string. All URIs are local.
-
-        @return 
-        '''
-        self.handling = 'lenient' # FCREPO does that and Hyrax requires it.
+        :param str update_str: SPARQL-Update string. All URIs are local.
+        """
+        # FCREPO does that and Hyrax requires it.
+        self.handling = 'lenient'
         delta = self._sparql_delta(update_str)
 
-        return self._modify_rsrc(RES_UPDATED, *delta)
+        self._modify_rsrc(RES_UPDATED, *delta)
 
 
     def _sparql_delta(self, q):
-        '''
+        """
         Calculate the delta obtained by a SPARQL Update operation.
 
         This is a critical component of the SPARQL update prcess and does a
@@ -855,10 +858,11 @@ class Ldpr(metaclass=ABCMeta):
         modified. If a server-managed term is present in the query but does not
         cause any change in the updated resource, no error is raised.
 
-        @return tuple(rdflib.Graph) Remove and add graphs. These can be used
-        with `BaseStoreLayout.update_resource` and/or recorded as separate
+        :rtype: tuple(rdflib.Graph)
+        :return: Remove and add graphs. These can be used
+        with ``BaseStoreLayout.update_resource`` and/or recorded as separate
         events in a provenance tracking system.
-        '''
+        """
         logger.debug('Provided SPARQL query: {}'.format(q))
         pre_gr = self.imr.graph
 

+ 12 - 24
lsup-admin

@@ -21,7 +21,7 @@ def admin():
 
 @click.command()
 def bootstrap():
-    '''
+    """
     Bootstrap binary and graph stores.
 
     This script will parse configuration files and initialize a filesystem and
@@ -29,7 +29,7 @@ def bootstrap():
     It is used in test suites and on a first run.
 
     Additional scaffolding files may be parsed to create initial contents.
-    '''
+    """
     import lakesuperior.env_setup
 
     rdfly = env.app_globals.rdfly
@@ -62,12 +62,12 @@ def bootstrap():
     '--human', '-h', is_flag=True, flag_value=True,
     help='Print a human-readable string. By default, JSON is printed.')
 def stats(human=False):
-    '''
+    """
     Print repository statistics.
 
     @param human (bool) Whether to output the data in human-readable
     format.
-    '''
+    """
     stat_data = admin_api.stats()
     if human:
         click.echo(
@@ -79,9 +79,9 @@ def stats(human=False):
 
 @click.command()
 def check_fixity(uid):
-    '''
+    """
     [STUB] Check fixity of a resource.
-    '''
+    """
     pass
 
 
@@ -116,22 +116,9 @@ def check_refint(config_folder=None):
 
 @click.command()
 def cleanup():
-    '''
+    """
     [STUB] Clean up orphan database items.
-    '''
-    pass
-
-
-@click.command()
-def copy():
-    '''
-    [STUB] Copy (backup) repository data.
-
-    This s a low-level copy, which backs up the data directories containing
-    graph and binary data. It may not even be a necessary command since to
-    back up the repository one just needs to copy the binary and metadata
-    folders.
-    '''
+    """
     pass
 
 
@@ -160,7 +147,7 @@ def copy():
     'process as usual.')
 @click_log.simple_verbosity_option(logger)
 def migrate(src, dest, start, list_file, zero_binaries, skip_errors):
-    '''
+    """
     Migrate an LDP repository to LAKEsuperior.
 
     This utility creates a fully functional LAKEshore repository from an
@@ -172,19 +159,20 @@ def migrate(src, dest, start, list_file, zero_binaries, skip_errors):
     populated with the RDF and binary data directories and a default
     configuration directory. The new repository can be immediately started
     from this location.
-    '''
+    """
     logger.info('Migrating {} into a new repository on {}.'.format(
             src, dest))
     entries = admin_api.migrate(
             src, dest, start_pts=start, list_file=list_file,
             zero_binaries=zero_binaries, skip_errors=skip_errors)
     logger.info('Migrated {} resources.'.format(entries))
-    logger.info('''Migration complete. To start the new repository, from the
+    logger.info("""Migration complete. To start the new repository, from the
     directory you launched this script run:
 
     FCREPO_CONFIG_DIR="{}/etc" ./fcrepo
 
     Make sure that the default port is not being used by another repository.
+    """.format(dest))
 
 
 admin.add_command(bootstrap)