Skip to content

Commit 7fa3666

Browse files
committed
Merge branch 'master' into 35229_add_additional_server_presets
2 parents 3d1def8 + 54c68db commit 7fa3666

File tree

6 files changed

+124
-45
lines changed

6 files changed

+124
-45
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ notifications:
1919
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (<a href="%{build_url}">Details</a>/<a href="%{compare_url}">Change view</a>)'
2020
format: html
2121
on_pull_requests: false
22+
slack:
23+
rooms:
24+
secure: NgcVxptQji2OL7EKx5owh21tOl4rRg51ydYhLPHpBIpBVzlqPxi1jbMHpcbl8mG+GuhU6y1D6kVQgQfuAfIWx5YOc4FodhOFZgeS+eol5RTmEepl1OT6XmAVgEclSZUYQmK25OkcxnFnOV/31RuDPXWcgCvSBZqTy6lAbOZ5VwQ=

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,26 @@ Integration and unit tests are provided.
4747

4848
[![Build Status](https://secure.travis-ci.org/shotgunsoftware/python-api.png?branch=master)](http://travis-ci.org/shotgunsoftware/python-api)
4949

50-
- test_client and tests_unit mock server interaction and do not require a shotgun instance to be available.
51-
- test_api and test_api_long do require a shotgun instance, with a script key available for the tests. These tests rely on a tests/config file, which can be created by renaming example_config and supplying the server and script user values. The tests will set up test data on the server based on the data set forth in the config. This data will be manipulated by the tests, and should not be used for other purposes.
52-
- To run all of the tests, use the shell script run-tests. This script require nose to be installed.
50+
- All tests require the "nose" unit testing tools (http://nose.readthedocs.org), and a "tests/config" file (copy from "tests/example_config").
51+
- Tests can be run individually like this: `nosetest tests/test_client.py`
52+
- test_client and tests_unit use mock server interaction and do not require a shotgun instance to be available (no modifacations to tests/config necessary).
53+
- test_api and test_api_long do require a shotgun instance, with a script key available for the tests. The server and script user values must be supplied in the tests/config file. The tests will set up test data on the server based on the data set forth in the config. This data will be manipulated by the tests, and should not be used for other purposes.
54+
- To run all of the tests, use the shell script run-tests.
5355

5456
## Changelog
5557

56-
**v3.0.28 - TBD**
58+
**v3.0.30.dev - TBD**
5759

5860
+ TBD
5961

62+
**v3.0.29 - 2016 Mar 7**
63+
64+
+ Reverted the change to the default field names for image uploading.
65+
66+
**v3.0.28 - 2016 Mar 3**
67+
68+
+ Refactored nested classing of sgtimezone library to allow for serializable timestamps.
69+
6070
**v3.0.27 - 2016 Feb 18**
6171

6272
+ Make sure HTTP proxy authentication works with the @ character in a password.

setup.py

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

1818
setup(
1919
name='shotgun_api3',
20-
version='3.0.28.dev',
20+
version='3.0.30.dev',
2121
description='Shotgun Python API ',
2222
long_description=readme,
2323
author='Shotgun Software',

shotgun_api3/lib/sgtimezone.py

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
# current users of api2 to install new modules and modify PYTHONPATH info.
66
# ----------------------------------------------------------------------------
77

8+
from datetime import tzinfo, timedelta, datetime
9+
import time as _time
10+
811
class SgTimezone(object):
9-
from datetime import tzinfo, timedelta, datetime
10-
import time as _time
12+
'''
13+
Shotgun's server infrastructure is configured for Coordinated Universal
14+
Time (UTC). In order to provide relevant local timestamps to users, we wrap
15+
the datetime module's tzinfo to provide convenient conversion methods.
16+
'''
1117

1218
ZERO = timedelta(0)
1319
STDOFFSET = timedelta(seconds = -_time.timezone)
@@ -18,41 +24,76 @@ class SgTimezone(object):
1824
DSTDIFF = DSTOFFSET - STDOFFSET
1925

2026
def __init__(self):
21-
self.utc = self.UTC()
22-
self.local = self.LocalTimezone()
27+
self.utc = UTC()
28+
self.local = LocalTimezone()
29+
30+
@classmethod
31+
def UTC(cls):
32+
'''
33+
For backwards compatibility, from when UTC was a nested class,
34+
we allow instantiation via SgTimezone
35+
'''
36+
return UTC()
37+
38+
@classmethod
39+
def LocalTimezone(cls):
40+
'''
41+
For backwards compatibility, from when LocalTimezone was a nested
42+
class, we allow instantiation via SgTimezone
43+
'''
44+
return LocalTimezone()
2345

24-
class UTC(tzinfo):
25-
26-
def utcoffset(self, dt):
27-
return SgTimezone.ZERO
28-
29-
def tzname(self, dt):
30-
return "UTC"
31-
32-
def dst(self, dt):
33-
return SgTimezone.ZERO
46+
class UTC(tzinfo):
47+
'''
48+
Implementation of datetime's tzinfo to provide consistent calculated
49+
offsets against Coordinated Universal Time (UTC)
50+
'''
51+
52+
def utcoffset(self, dt):
53+
return SgTimezone.ZERO
3454

35-
class LocalTimezone(tzinfo):
36-
37-
def utcoffset(self, dt):
38-
if self._isdst(dt):
39-
return SgTimezone.DSTOFFSET
40-
else:
41-
return SgTimezone.STDOFFSET
42-
43-
def dst(self, dt):
44-
if self._isdst(dt):
45-
return SgTimezone.DSTDIFF
46-
else:
47-
return SgTimezone.ZERO
48-
49-
def tzname(self, dt):
50-
return _time.tzname[self._isdst(dt)]
51-
52-
def _isdst(self, dt):
53-
tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)
54-
import time as _time
55-
stamp = _time.mktime(tt)
56-
tt = _time.localtime(stamp)
57-
return tt.tm_isdst > 0
55+
def tzname(self, dt):
56+
return "UTC"
57+
58+
def dst(self, dt):
59+
return SgTimezone.ZERO
5860

61+
class LocalTimezone(tzinfo):
62+
'''
63+
Implementation of datetime's tzinfo to provide convenient conversion
64+
between Shotgun server time and local user time
65+
'''
66+
67+
def utcoffset(self, dt):
68+
'''
69+
Difference between the user's local timezone and UTC timezone in seconds
70+
'''
71+
if self._isdst(dt):
72+
return SgTimezone.DSTOFFSET
73+
else:
74+
return SgTimezone.STDOFFSET
75+
76+
def dst(self, dt):
77+
'''
78+
Daylight savings time (dst) offset in seconds
79+
'''
80+
if self._isdst(dt):
81+
return SgTimezone.DSTDIFF
82+
else:
83+
return SgTimezone.ZERO
84+
85+
def tzname(self, dt):
86+
'''
87+
Name of the user's local timezone, including a reference
88+
to daylight savings time (dst) if applicable
89+
'''
90+
return _time.tzname[self._isdst(dt)]
91+
92+
def _isdst(self, dt):
93+
'''
94+
Calculate whether the timestamp in question was in daylight savings
95+
'''
96+
tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)
97+
stamp = _time.mktime(tt)
98+
tt = _time.localtime(stamp)
99+
return tt.tm_isdst > 0

shotgun_api3/shotgun.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878

7979
# ----------------------------------------------------------------------------
8080
# Version
81-
__version__ = "3.0.28.dev"
81+
__version__ = "3.0.30.dev"
8282

8383
# ----------------------------------------------------------------------------
8484
# Errors
@@ -255,6 +255,8 @@ def __init__(self):
255255
self.user_password = None
256256
self.auth_token = None
257257
self.sudo_as_login = None
258+
# Authentication parameters to be folded into final auth_params dict
259+
self.extra_auth_params = None
258260
# uuid as a string
259261
self.session_uuid = None
260262
self.scheme = None
@@ -1449,7 +1451,7 @@ def upload_thumbnail(self, entity_type, entity_id, path, **kwargs):
14491451
:returns: Id of the new attachment
14501452
"""
14511453
return self.upload(entity_type, entity_id, path,
1452-
field_name="image", **kwargs)
1454+
field_name="thumb_image", **kwargs)
14531455

14541456
def upload_filmstrip_thumbnail(self, entity_type, entity_id, path, **kwargs):
14551457
"""Convenience function for uploading filmstrip thumbnails.
@@ -1467,7 +1469,7 @@ def upload_filmstrip_thumbnail(self, entity_type, entity_id, path, **kwargs):
14671469
"higher, server is %s" % (self.server_caps.version,))
14681470

14691471
return self.upload(entity_type, entity_id, path,
1470-
field_name="filmstrip_image", **kwargs)
1472+
field_name="filmstrip_thumb_image", **kwargs)
14711473

14721474
def upload(self, entity_type, entity_id, path, field_name=None,
14731475
display_name=None, tag_list=None):
@@ -2148,6 +2150,9 @@ def _auth_params(self):
21482150
"higher, server is %s" % (self.server_caps.version,))
21492151
auth_params["sudo_as_login"] = self.config.sudo_as_login
21502152

2153+
if self.config.extra_auth_params:
2154+
auth_params.update(self.config.extra_auth_params)
2155+
21512156
return auth_params
21522157

21532158
def _sanitize_auth_params(self, params):

tests/test_client.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ def test_server_version_json(self):
8989
sc.version = (2,5,0)
9090
sc._ensure_json_supported()
9191

92+
def test_extra_auth_params(self):
93+
"""test_extra_auth_params tests provided auth_params are included in request"""
94+
# ok for the mock server to just return an error, we want to look at
95+
# what's in the request
96+
self._mock_http({ "message":"Go BANG",
97+
"exception":True })
98+
99+
def auth_args():
100+
args = self.sg._http_request.call_args[0]
101+
body = args[2]
102+
body = json.loads(body)
103+
return body["params"][0]
104+
105+
self.sg.config.extra_auth_params = None
106+
self.assertRaises(api.Fault, self.sg.delete, "FakeType", 1)
107+
self.assertTrue("product" not in auth_args())
108+
109+
self.sg.config.extra_auth_params = {"product":"rv"}
110+
self.assertRaises(api.Fault, self.sg.delete, "FakeType", 1)
111+
self.assertEqual("rv", auth_args()["product"])
92112

93113
def test_session_uuid(self):
94114
"""test_session_uuid tests session UUID is included in request"""

0 commit comments

Comments
 (0)