@@ -753,6 +753,66 @@ def _touch_cache(self, path):
753753 return touch_access_time (path_to_hashed )
754754
755755
756+ def board_deparse (board : BaseBoard ):
757+ """Return a representation of how a board could be reconstructed.
758+
759+ Note that this function does not try to represent the exact arguments used
760+ to construct a board, but key pieces (like the path to the board). You may
761+ need to specify environment variables with API keys to complete the connection.
762+
763+ Parameters
764+ ----------
765+ board:
766+ A pins board to be represented.
767+
768+ Examples
769+ --------
770+
771+ The example below deparses a board connected to Posit Connect.
772+
773+ >>> from pins.constructors import board_connect
774+ >>> board_deparse(board_connect(server_url="http://example.com", api_key="xxx"))
775+ "board_connect(server_url='http://example.com')"
776+
777+ Note that the deparsing a Posit Connect board does not keep the api_key,
778+ which is sensitive information. In this case, you can set the CONNECT_API_KEY
779+ environment variable to connect.
780+
781+ Below is an example of representing a board connected to a local folder.
782+
783+ >>> from pins.constructors import board_folder
784+ >>> board_deparse(board_folder("a/b/c"))
785+ "board_folder('a/b/c')"
786+
787+ >>> board_deparse(board_folder(path="a/b/c", allow_pickle_read=True))
788+ "board_folder('a/b/c', allow_pickle_read=True)"
789+ """
790+ if board .allow_pickle_read is not None :
791+ allow_pickle = f", allow_pickle_read={ repr (board .allow_pickle_read )} "
792+ else :
793+ allow_pickle = ""
794+
795+ prot = board .fs .protocol
796+
797+ if prot == "rsc" :
798+ url = board .fs .api .server_url
799+ return f"board_connect(server_url={ repr (url )} { allow_pickle } )"
800+ elif prot in ["file" , ("file" , "local" )]:
801+ return f"board_folder({ repr (board .board )} { allow_pickle } )"
802+ elif set (prot ) == {"s3" , "s3a" }:
803+ return f"board_s3({ repr (board .board )} { allow_pickle } )"
804+ elif prot == "abfs" :
805+ return f"board_azure({ repr (board .board )} { allow_pickle } )"
806+ elif set (prot ) == {"gcs" , "gs" } or prot == "gs" :
807+ return f"board_gcs({ repr (board .board )} { allow_pickle } )"
808+ elif prot == "http" :
809+ return f"board_url({ repr (board .board )} , { board .pin_paths } { allow_pickle } )"
810+ else :
811+ raise NotImplementedError (
812+ f"board deparsing currently not supported for protocol: { prot } "
813+ )
814+
815+
756816class BoardManual (BaseBoard ):
757817 """Simple board that accepts a dictionary of form `pin_name: path`.
758818
@@ -1089,9 +1149,6 @@ def user_name(self):
10891149 return self ._user_name
10901150
10911151 def prepare_pin_version (self , pin_dir_path , x , name : "str | None" , * args , ** kwargs ):
1092- # TODO: should move board_deparse into utils, to avoid circular import
1093- from .constructors import board_deparse
1094-
10951152 # RSC pin names can have form <user_name>/<name>, but this will try to
10961153 # create the object in a directory named <user_name>. So we grab just
10971154 # the <name> part.
0 commit comments