@@ -21,6 +21,7 @@ def board(
2121 path : str = "" ,
2222 versioned : bool = True ,
2323 cache : "DEFAULT | None" = DEFAULT ,
24+ allow_pickle_read = None ,
2425 storage_options : "dict | None" = None ,
2526 board_factory : "callable | BaseBoard | None" = None ,
2627):
@@ -39,6 +40,14 @@ def board(
3940 Whether to use a cache. By default, pins attempts to select the right cache
4041 directory, given your filesystem. If None is passed, then no cache will be
4142 used. You can set the cache using the PINS_CACHE_DIR environment variable.
43+ allow_pickle_read: optional, bool
44+ Whether to allow reading pins that use the pickle protocol. Pickles are unsafe,
45+ and can execute arbitrary code. Only allow reading pickles if you trust the
46+ board to be able to execute python code on your computer.
47+
48+ You can enable reading pickles by setting this to True, or by setting the
49+ environment variable PINS_ALLOW_PICKLE_READ. If both are set, this argument
50+ takes precedence.
4251 storage_options:
4352 Additional options passed to the underlying filesystem created by
4453 fsspec.filesystem.
@@ -72,27 +81,50 @@ def board(
7281
7382 # construct board ----
7483
84+ pickle_kwargs = {"allow_pickle_read" : allow_pickle_read }
7585 # TODO: should use a registry or something
7686 if protocol == "rsc" and board_factory is None :
77- board = BoardRsConnect (path , fs , versioned )
87+ board = BoardRsConnect (path , fs , versioned , ** pickle_kwargs )
7888 elif board_factory is not None :
79- board = board_factory (path , fs , versioned )
89+ board = board_factory (path , fs , versioned , ** pickle_kwargs )
8090 else :
81- board = BaseBoard (path , fs , versioned )
91+ board = BaseBoard (path , fs , versioned , ** pickle_kwargs )
8292 return board
8393
8494
8595# TODO(#31): change file boards to unversioned once implemented
8696
8797
88- def board_folder (path , versioned = True ):
89- return board ("file" , path , versioned , cache = None )
98+ def board_folder (path : str , versioned = True , allow_pickle_read = None ):
99+ """Create a pins board inside a folder.
100+
101+ Parameters
102+ ----------
103+ path:
104+ The folder that will hold the board.
105+ **kwargs:
106+ Passed to the pins.board function.
107+ """
108+
109+ return board (
110+ "file" , path , versioned , cache = None , allow_pickle_read = allow_pickle_read
111+ )
90112
91113
92- def board_temp (versioned = True ):
114+ def board_temp (versioned = True , allow_pickle_read = None ):
115+ """Create a pins board in a temporary directory.
116+
117+ Parameters
118+ ----------
119+ **kwargs:
120+ Passed to the pins.board function.
121+ """
122+
93123 tmp_dir = tempfile .TemporaryDirectory ()
94124
95- board_obj = board ("file" , tmp_dir .name , versioned , cache = None )
125+ board_obj = board (
126+ "file" , tmp_dir .name , versioned , cache = None , allow_pickle_read = allow_pickle_read
127+ )
96128
97129 # TODO: this is necessary to ensure the temporary directory dir persists.
98130 # without maintaining a reference to it, it could be deleted after this
@@ -102,26 +134,36 @@ def board_temp(versioned=True):
102134 return board_obj
103135
104136
105- def board_local (versioned = True ):
137+ def board_local (versioned = True , allow_pickle_read = None ):
138+ """Create a board in a system data directory.
139+
140+ Parameters
141+ ----------
142+ **kwargs:
143+ Passed to the pins.board function.
144+ """
106145 path = get_data_dir ()
107146
108- return board ("file" , path , versioned , cache = None )
147+ return board (
148+ "file" , path , versioned , cache = None , allow_pickle_read = allow_pickle_read
149+ )
109150
110151
111- def board_github (org , repo , path = "" , versioned = True , cache = DEFAULT ):
152+ def board_github (
153+ org , repo , path = "" , versioned = True , cache = DEFAULT , allow_pickle_read = None
154+ ):
112155 """Returns a github pin board.
113156
114157 Parameters
115158 ----------
116- path:
117- TODO
118- versioned:
119- TODO
120159 org:
121160 Name of the github org (e.g. user account).
122161 repo:
123162 Name of the repo.
124-
163+ path:
164+ A subfolder in the github repo holding the board.
165+ **kwargs:
166+ Passed to the pins.board function.
125167
126168 Note
127169 ----
@@ -144,12 +186,26 @@ def board_github(org, repo, path="", versioned=True, cache=DEFAULT):
144186 """
145187
146188 return board (
147- "github" , path , versioned , cache , storage_options = {"org" : org , "repo" : repo }
189+ "github" ,
190+ path ,
191+ versioned ,
192+ cache ,
193+ allow_pickle_read = allow_pickle_read ,
194+ storage_options = {"org" : org , "repo" : repo },
148195 )
149196
150197
151- def board_urls (path : str , pin_paths : dict , cache = DEFAULT ):
152- """
198+ def board_urls (path : str , pin_paths : dict , cache = DEFAULT , allow_pickle_read = None ):
199+ """Create a board from individual urls.
200+
201+ Parameters
202+ ----------
203+ path:
204+ A base url to prefix all individual pin urls with.
205+ pin_paths: Mapping
206+ A dictionary mapping pin name to pin url .
207+ **kwargs:
208+ Passed to the pins.board function.
153209
154210 Example
155211 -------
@@ -175,18 +231,29 @@ def board_urls(path: str, pin_paths: dict, cache=DEFAULT):
175231 else :
176232 raise NotImplementedError ("Can't currently pass own cache object" )
177233
178- return BoardManual (path , fs , versioned = True , pin_paths = pin_paths )
234+ return BoardManual (
235+ path ,
236+ fs ,
237+ versioned = True ,
238+ allow_pickle_read = allow_pickle_read ,
239+ pin_paths = pin_paths ,
240+ )
179241
180242
181- def board_rsconnect (versioned = True , server_url = None , api_key = None , cache = DEFAULT ):
182- """
243+ def board_rsconnect (
244+ versioned = True , server_url = None , api_key = None , cache = DEFAULT , allow_pickle_read = None
245+ ):
246+ """Create a board to read and write pins from an RStudio Connect instance.
183247
184248 Parameters
185249 ----------
186250 server_url:
187- TODO
251+ Url to the RStudio Connect server.
188252 api_key:
189- TODO
253+ API key for server. If not specified, pins will attempt to read it from
254+ CONNECT_API_KEY environment variable.
255+ **kwargs:
256+ Passed to the pins.board function.
190257 """
191258
192259 # TODO: api_key can be passed in to underlying RscApi, equiv to R's manual mode
@@ -196,9 +263,18 @@ def board_rsconnect(versioned=True, server_url=None, api_key=None, cache=DEFAULT
196263 server_url = os .environ .get ("CONNECT_SERVER" )
197264
198265 kwargs = dict (server_url = server_url , api_key = api_key )
199- return board ("rsc" , "" , versioned , storage_options = kwargs )
266+ return board ("rsc" , "" , versioned , cache , allow_pickle_read , storage_options = kwargs )
267+
200268
269+ def board_s3 (path , versioned = True , cache = DEFAULT , allow_pickle_read = None ):
270+ """Create a board to read and write pins from an AWS S3 bucket folder.
201271
202- def board_s3 (path , versioned = True ):
272+ Parameters
273+ ----------
274+ path:
275+ Path of form <bucket_name>/<optional>/<subdirectory>.
276+ **kwargs:
277+ Passed to the pins.board function.
278+ """
203279 # TODO: user should be able to specify storage options here?
204- return board ("s3" , path , versioned )
280+ return board ("s3" , path , versioned , cache , allow_pickle_read )
0 commit comments