Skip to content

Commit feddaa0

Browse files
SG-35561 export csv python changes (#386)
* changes to export page from the api * uncommented other test cases * doc string added in export_page function * args positioning changed * updated according to new export page params * update the doc string * removed extra line added * test cases updated * test case fixed * test case updated * update in test cases * update for human_user authmode * update in mock test cases * update in docs, and version number updated * update in doc string * update the documentation link * removing merge conflicts with update in documentation * update the test cases * release notes updated * small doc changes added * packaging for the v3.9.2 release * Revert "packaging for the v3.9.2 release" This reverts commit d359d05. * packaging for the v3.9.2 release * updated history for release info
1 parent 89e083d commit feddaa0

File tree

5 files changed

+110
-2
lines changed

5 files changed

+110
-2
lines changed

HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Flow Production Tracking Python API Changelog
44

55
Here you can see the full list of changes between each Python API release.
66

7+
v3.9.2 (2025 Dec 10)
8+
===================
9+
10+
- Add ``export_page`` method to Shotgun class.
11+
- Documentation has been updated to reflect this addition.
12+
713
v3.9.1 (2025 Nov 25)
814
====================
915

docs/reference.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ The documentation for all of the methods you'll need in your scripts lives in he
6666
Shotgun.work_schedule_read
6767
Shotgun.work_schedule_update
6868
Shotgun.preferences_read
69+
Shotgun.export_page
6970

7071
.. rubric:: Working With Files
7172

@@ -150,6 +151,7 @@ also some specialized convenience methods for accessing particular types of info
150151
.. automethod:: Shotgun.work_schedule_read
151152
.. automethod:: Shotgun.work_schedule_update
152153
.. automethod:: Shotgun.preferences_read
154+
.. automethod:: Shotgun.export_page
153155

154156
Working With Files
155157
==================

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
setup(
2222
name="shotgun_api3",
23-
version="3.9.1",
23+
version="3.9.2",
2424
description="Flow Production Tracking Python API",
2525
long_description=readme,
2626
author="Autodesk",

shotgun_api3/shotgun.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494

9595
# ----------------------------------------------------------------------------
9696
# Version
97-
__version__ = "3.9.1"
97+
__version__ = "3.9.2"
9898

9999

100100
# ----------------------------------------------------------------------------
@@ -1882,6 +1882,29 @@ def work_schedule_update(
18821882

18831883
return self._call_rpc("work_schedule_update", params)
18841884

1885+
def export_page(self, page_id, format, layout_name=None):
1886+
"""
1887+
Export the specified page to the given format.
1888+
This method allows you to export a page to CSV.
1889+
Respective layout or page should be marked as API Exportable in the Flow Production Tracking UI.
1890+
For more information, see documentation_.
1891+
.. _documentation: https://help.autodesk.com/view/SGSUB/ENU/?guid=SG_Tutorials_tu_export_csv_html#enable-api-export-for-a-page
1892+
If ``layout_name`` is not passed in, the default layout name will be used.
1893+
>>> sg.export_page(12345, "csv", layout_name="My Layout")
1894+
"ID,Name,Status\\n1,Shot 001,ip\\n2, Shot 002,rev\\n"
1895+
>>> sg.export_page(12345, "csv")
1896+
"ID,Name,Status\\n1,Shot 001,ip\\n2,Shot 002,rev\\n"
1897+
:param int page_id: The ID of the page to export.
1898+
:param str format: The format to export the page to. Supported format is ``"csv"``.
1899+
:param str layout_name: Optional layout name. This should be the name of the layout seen in the Flow Production Tracking UI.
1900+
:returns: string containing data of the given page.
1901+
:rtype: string
1902+
"""
1903+
1904+
params = dict(format=format, page_id=page_id, layout_name=layout_name)
1905+
1906+
return self._call_rpc("export_page", params)
1907+
18851908
def follow(self, user: Dict[str, Any], entity: Dict[str, Any]) -> Dict[str, Any]:
18861909
"""
18871910
Add the entity to the user's followed entities.

tests/test_api.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,83 @@ def test_include_archived_projects(self):
19471947
self.sg.update("Project", self.project["id"], {"archived": False})
19481948

19491949

1950+
class TestExportPage(base.LiveTestBase):
1951+
1952+
def setUp(self):
1953+
super(TestExportPage, self).setUp("HumanUser")
1954+
1955+
def test_export_page_unavailable(self):
1956+
"""
1957+
Test export_page raises when report does not exist.
1958+
"""
1959+
if not self.sg.server_caps.version or self.sg.server_caps.version < (5, 1, 22):
1960+
return
1961+
1962+
page_entity = self.sg.create("Page", {"entity_type": "Shot"})
1963+
1964+
with self.assertRaises(Exception) as cm:
1965+
self.sg.export_page(page_entity["id"], "csv")
1966+
self.assertIn(
1967+
f"This functionality is currently not available", str(cm.exception)
1968+
)
1969+
1970+
with self.assertRaises(Exception) as cm:
1971+
self.sg.export_page(page_entity["id"], "csv", layout_name="My Layout")
1972+
self.assertIn(
1973+
f"This functionality is currently not available", str(cm.exception)
1974+
)
1975+
1976+
def test_export_page_format_missing(self):
1977+
"""
1978+
Test export_page raises for invalid format.
1979+
"""
1980+
if not self.sg.server_caps.version or self.sg.server_caps.version < (5, 1, 22):
1981+
return
1982+
1983+
with self.assertRaises(Exception) as cm:
1984+
self.sg.export_page(11, None)
1985+
self.assertIn("'format' missing", str(cm.exception))
1986+
1987+
with self.assertRaises(Exception) as cm:
1988+
self.sg.export_page(11, None, layout_name="My Layout")
1989+
self.assertIn("'format' missing", str(cm.exception))
1990+
1991+
def test_export_page_missing_page_id(self):
1992+
"""
1993+
Test export_page raises for missing page id.
1994+
"""
1995+
if not self.sg.server_caps.version or self.sg.server_caps.version < (5, 1, 22):
1996+
return
1997+
1998+
with self.assertRaises(Exception) as cm:
1999+
self.sg.export_page(None, "csv")
2000+
self.assertIn("'page_id' missing", str(cm.exception))
2001+
2002+
with self.assertRaises(Exception) as cm:
2003+
self.sg.export_page(None, "csv", layout_name="My Layout")
2004+
self.assertIn("'page_id' missing", str(cm.exception))
2005+
2006+
@unittest.mock.patch("shotgun_api3.shotgun.Http.request")
2007+
def test_export_page_without_layout_name(self, mock_request):
2008+
"""
2009+
Test export_page works when layout_name is not provided.
2010+
"""
2011+
2012+
if not self.sg.server_caps.version or self.sg.server_caps.version < (5, 1, 22):
2013+
return
2014+
2015+
# Mock the underlying Http.request to return CSV content with appropriate headers
2016+
csv_body = "ID,Name,Status\n1,Shot 001,ip\n2,Shot 002,rev\n"
2017+
response = unittest.mock.MagicMock(name="response mock")
2018+
response.status = 200
2019+
response.reason = "OK"
2020+
response.items.return_value = [("content-type", "text/csv; charset=utf-8")]
2021+
mock_request.return_value = (response, csv_body)
2022+
result = self.sg.export_page(11, "csv")
2023+
self.assertIsInstance(result, str)
2024+
self.assertTrue(result.startswith("ID,Name,Status"))
2025+
2026+
19502027
class TestFollow(base.LiveTestBase):
19512028

19522029
def test_follow_unfollow(self):

0 commit comments

Comments
 (0)