Skip to content

Commit 41a3c36

Browse files
committed
feat!: support public rsc pin read, using manual board
1 parent 8915c12 commit 41a3c36

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

pins/boards.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ class BoardManual(BaseBoard):
637637
>>> import fsspec
638638
>>> import os
639639
>>> fs = fsspec.filesystem("github", org = "machow", repo = "pins-python")
640-
>>> pin_paths = {"df_csv": "df_csv/20220214T163720Z-9bfad"}
640+
>>> pin_paths = {"df_csv": "df_csv/20220214T163720Z-9bfad/"}
641641
>>> board = BoardManual("pins/tests/pins-compat", fs, pin_paths=pin_paths)
642642
643643
>>> board.pin_list()
@@ -690,7 +690,9 @@ def pin_meta(self, name, version=None):
690690
# create metadata, rather than read from a file
691691
return self.meta_factory.create_raw(path_to_pin, type="file", name=pin_name)
692692

693-
path_meta = self.construct_path([pin_name, meta_name])
693+
# note that pins on this board should point to versions, so we use an
694+
# empty string to mark version (it ultimately is ignored)
695+
path_meta = self.construct_path([pin_name, "", meta_name])
694696
f = self._open_pin_meta(path_meta)
695697
meta = self.meta_factory.read_pin_yaml(f, pin_name, VersionRaw(""))
696698

@@ -717,21 +719,30 @@ def construct_path(self, elements):
717719
pin_name, *others = elements
718720
pin_path = self.pin_paths[pin_name]
719721

720-
if self.board.strip() == "":
721-
return pin_path
722+
pre_components = [] if not self.board else [self.board]
722723

723-
if len(others):
724-
# this is confusing, but R pins url board has a final "/" indicate that
725-
# something is a pin version, rather than a single file. but since other
726-
# boards forbid a final /, we need to strip it off to join elements
727-
pin_path = pin_path.rstrip().rstrip("/")
724+
# note that for paths where version is specified, it gets omitted,
725+
# since pin_path should point to a pin version
726+
if not pin_path.endswith("/"):
727+
if len(others):
728+
raise ValueError(
729+
f"pin path {pin_path} does not end in '/' so is assumed to be a"
730+
f" single file. Cannot construct a path to elements {elements}."
731+
)
732+
return "/".join(pre_components + [pin_path])
733+
elif len(others) == 0:
734+
return "/".join(pre_components + [pin_path])
735+
elif len(others) == 1:
736+
version = others[0]
737+
return "/".join(pre_components + [pin_path])
738+
elif len(others) == 2:
739+
version, meta = others
728740

729-
# this is a bit hacky, but this board only aims at specific pins versions,
730-
# so the metadata has the version as "", so we need to remove it.
731-
if others[0] == "":
732-
return super().construct_path([pin_path, *others[1:]])
741+
return "/".join(pre_components + [pin_path, meta])
733742

734-
return super().construct_path([pin_path, *others])
743+
raise NotImplementedError(
744+
f"Unable to construct path from these elements: {elements}"
745+
)
735746

736747

737748
class BoardRsConnect(BaseBoard):

pins/rsconnect/fs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ def put(
201201
except RsConnectApiMissingContentError:
202202
# TODO: this could be seen as analogous to mkdir (which gets
203203
# called by pins anyway)
204-
# TODO: hard-coded acl bad?
205204
content = self.api.post_content_item(parsed.content, access_type)
206205

207206
# Create bundle (with manifest.json inserted if missing) ----

pins/tests/test_boards.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,23 @@ def test_board_rsc_pin_write_acl(df, board_short):
441441
assert content["access_type"] == "all"
442442

443443

444+
@pytest.mark.fs_rsc
445+
def test_board_rsc_pin_read_public(df, board_short):
446+
from pins.boards import BoardManual
447+
448+
board_short.pin_write(df, "susan/mtcars", type="csv", access_type="all")
449+
450+
# note that users can also get this from the web ui
451+
content_url = board_short.fs.info("susan/mtcars")["content_url"]
452+
453+
# shouldn't be a key set in env, but remove just in case
454+
fs = fsspec.filesystem("http")
455+
board_url = BoardManual("", fs, pin_paths={"rsc_public": content_url})
456+
457+
df_no_key = board_url.pin_read("rsc_public")
458+
assert df_no_key.equals(df)
459+
460+
444461
# Manual Board Specific =======================================================
445462

446463
from pins.boards import BoardManual # noqa

0 commit comments

Comments
 (0)