Hello community, here is the log from the commit of package python-msrest for openSUSE:Factory checked in at 2018-05-13 16:03:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-msrest (Old) and /work/SRC/openSUSE:Factory/.python-msrest.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-msrest" Sun May 13 16:03:43 2018 rev:5 rq:601547 version:0.4.28 Changes: -------- --- /work/SRC/openSUSE:Factory/python-msrest/python-msrest.changes 2018-02-14 09:27:23.732669346 +0100 +++ /work/SRC/openSUSE:Factory/.python-msrest.new/python-msrest.changes 2018-05-13 16:03:43.821253496 +0200 @@ -1,0 +2,13 @@ +Tue Apr 24 10:52:43 UTC 2018 - [email protected] + +- New upstream release + + Version 0.4.28 + + For detailed information about changes see the + README.rst file provided with this package +- Install HISTORY.rst into doc directory +- Refresh patches for new version + + m_drop-compatible-releases-operator.patch + + m_drop-extras-require.patch +- Update Requires from setup.py + +------------------------------------------------------------------- Old: ---- msrest-0.4.25.tar.gz New: ---- msrest-0.4.28.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-msrest.spec ++++++ --- /var/tmp/diff_new_pack.xnQbrx/_old 2018-05-13 16:03:44.549226937 +0200 +++ /var/tmp/diff_new_pack.xnQbrx/_new 2018-05-13 16:03:44.549226937 +0200 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-msrest -Version: 0.4.25 +Version: 0.4.28 Release: 0 Summary: AutoRest swagger generator Python client runtime License: MIT @@ -32,7 +32,7 @@ BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-certifi >= 2017.4.17 -Requires: python-isodate >= 0.5.4 +Requires: python-isodate >= 0.6.0 Requires: python-requests < 3.00 Requires: python-requests >= 2.14 Requires: python-requests-oauthlib >= 0.5.0 @@ -60,6 +60,7 @@ %files %{python_files} %defattr(-,root,root,-) +%doc README.rst %{python_sitelib}/* %changelog ++++++ m_drop-compatible-releases-operator.patch ++++++ --- /var/tmp/diff_new_pack.xnQbrx/_old 2018-05-13 16:03:44.573226061 +0200 +++ /var/tmp/diff_new_pack.xnQbrx/_new 2018-05-13 16:03:44.573226061 +0200 @@ -1,12 +1,12 @@ -diff -Nru msrest-0.4.11.orig/setup.py msrest-0.4.11/setup.py ---- msrest-0.4.11.orig/setup.py 2017-06-21 21:21:28.000000000 +0200 -+++ msrest-0.4.11/setup.py 2017-09-19 21:48:38.208520870 +0200 -@@ -48,7 +48,7 @@ +diff -Nru msrest-0.4.28.orig/setup.py msrest-0.4.28/setup.py +--- msrest-0.4.28.orig/setup.py 2018-04-18 23:08:15.000000000 +0200 ++++ msrest-0.4.28/setup.py 2018-04-24 12:46:33.099513431 +0200 +@@ -47,7 +47,7 @@ 'License :: OSI Approved :: MIT License', 'Topic :: Software Development'], install_requires=[ - "requests~=2.14", + "requests>=2.14", "requests_oauthlib>=0.5.0", - "isodate>=0.5.4", + "isodate>=0.6.0", "certifi>=2017.4.17", ++++++ m_drop-extras-require.patch ++++++ --- /var/tmp/diff_new_pack.xnQbrx/_old 2018-05-13 16:03:44.585225624 +0200 +++ /var/tmp/diff_new_pack.xnQbrx/_new 2018-05-13 16:03:44.585225624 +0200 @@ -1,13 +1,11 @@ -diff -Nru msrest-0.4.11.orig/setup.py msrest-0.4.11/setup.py ---- msrest-0.4.11.orig/setup.py 2017-09-19 21:48:38.208520870 +0200 -+++ msrest-0.4.11/setup.py 2017-09-19 21:50:56.557685936 +0200 -@@ -52,8 +52,5 @@ - "requests_oauthlib>=0.5.0", - "isodate>=0.5.4", +diff -Nru msrest-0.4.28.orig/setup.py msrest-0.4.28/setup.py +--- msrest-0.4.28.orig/setup.py 2018-04-24 12:46:33.099513431 +0200 ++++ msrest-0.4.28/setup.py 2018-04-24 12:47:31.784002289 +0200 +@@ -52,7 +52,4 @@ + "isodate>=0.6.0", "certifi>=2017.4.17", -- ], + ], - extras_require={ - ":python_version<'3.4'": ['enum34>=1.0.4'], - } -+ ] ) ++++++ msrest-0.4.25.tar.gz -> msrest-0.4.28.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/PKG-INFO new/msrest-0.4.28/PKG-INFO --- old/msrest-0.4.25/PKG-INFO 2018-01-08 22:52:45.000000000 +0100 +++ new/msrest-0.4.28/PKG-INFO 2018-04-18 23:08:55.000000000 +0200 @@ -1,14 +1,13 @@ Metadata-Version: 1.1 Name: msrest -Version: 0.4.25 +Version: 0.4.28 Summary: AutoRest swagger generator Python client runtime. Home-page: https://github.com/Azure/msrest-for-python Author: Microsoft Corporation Author-email: UNKNOWN License: MIT License -Description-Content-Type: UNKNOWN Description: AutoRest: Python Client Runtime - ================================ + =============================== .. image:: https://travis-ci.org/Azure/msrest-for-python.svg?branch=master :target: https://travis-ci.org/Azure/msrest-for-python @@ -29,6 +28,49 @@ Release History --------------- + 2018-04-18 Version 0.4.28 + +++++++++++++++++++++++++ + + **Features** + + - msrest is now able to keep the "requests.Session" alive for performance. To activate this behavior: + + - Use the final Client as a context manager (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and `client.close()` (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and client._client.close() (not recommended, but available in old releases of SDK) + + - All Authentication classes now define `signed_session` and `refresh_session` with an optional `session` parameter. + To take benefits of the session improvement, a subclass of Authentication *MUST* add this optional parameter + and use it if it's not `None`: + + def signed_session(self, session=None): + session = session or requests.Session() + + # As usual from here. + + 2018-03-07 Version 0.4.27 + +++++++++++++++++++++++++ + + **Features** + + - Disable HTTP log by default (security), add `enable_http_log` to restore it #86 + + **BugFixes** + + - Fix incorrect date parsing if ms precision is over 6 digits #82 + + 2018-01-30 Version 0.4.26 + +++++++++++++++++++++++++ + + **Features** + + - Add TopicCredentials for EventGrid client + + **Bugfixes** + + - Fix minimal dependency of isodate + - Fix serialisation from dict if datetime provided + 2018-01-08 Version 0.4.25 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/README.rst new/msrest-0.4.28/README.rst --- old/msrest-0.4.25/README.rst 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/README.rst 2018-04-18 23:08:15.000000000 +0200 @@ -1,5 +1,5 @@ AutoRest: Python Client Runtime -================================ +=============================== .. image:: https://travis-ci.org/Azure/msrest-for-python.svg?branch=master :target: https://travis-ci.org/Azure/msrest-for-python @@ -20,6 +20,49 @@ Release History --------------- +2018-04-18 Version 0.4.28 ++++++++++++++++++++++++++ + +**Features** + +- msrest is now able to keep the "requests.Session" alive for performance. To activate this behavior: + + - Use the final Client as a context manager (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and `client.close()` (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and client._client.close() (not recommended, but available in old releases of SDK) + +- All Authentication classes now define `signed_session` and `refresh_session` with an optional `session` parameter. + To take benefits of the session improvement, a subclass of Authentication *MUST* add this optional parameter + and use it if it's not `None`: + + def signed_session(self, session=None): + session = session or requests.Session() + + # As usual from here. + +2018-03-07 Version 0.4.27 ++++++++++++++++++++++++++ + +**Features** + +- Disable HTTP log by default (security), add `enable_http_log` to restore it #86 + +**BugFixes** + +- Fix incorrect date parsing if ms precision is over 6 digits #82 + +2018-01-30 Version 0.4.26 ++++++++++++++++++++++++++ + +**Features** + +- Add TopicCredentials for EventGrid client + +**Bugfixes** + +- Fix minimal dependency of isodate +- Fix serialisation from dict if datetime provided + 2018-01-08 Version 0.4.25 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/__init__.py new/msrest-0.4.28/msrest/__init__.py --- old/msrest-0.4.25/msrest/__init__.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/__init__.py 2018-04-18 23:08:15.000000000 +0200 @@ -25,12 +25,13 @@ # -------------------------------------------------------------------------- from .configuration import Configuration -from .service_client import ServiceClient +from .service_client import ServiceClient, SDKClient from .serialization import Serializer, Deserializer from .version import msrest_version __all__ = [ "ServiceClient", + "SDKClient", "Serializer", "Deserializer", "Configuration" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/authentication.py new/msrest-0.4.28/msrest/authentication.py --- old/msrest-0.4.25/msrest/authentication.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/authentication.py 2018-04-18 23:08:15.000000000 +0200 @@ -36,17 +36,21 @@ header = "Authorization" - def signed_session(self): - """Create requests session with any required auth headers - applied. + def signed_session(self, session=None): + """Create requests session with any required auth headers applied. + + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. - :rtype: requests.Session. + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - return requests.Session() + return session or requests.Session() class BasicAuthentication(Authentication): - """Implmentation of Basic Authentication. + """Implementation of Basic Authentication. :param str username: Authentication username. :param str password: Authentication password. @@ -57,13 +61,18 @@ self.username = username self.password = password - def signed_session(self): + def signed_session(self, session=None): """Create requests session with any required auth headers applied. - :rtype: requests.Session. + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - session = super(BasicAuthentication, self).signed_session() + session = super(BasicAuthentication, self).signed_session(session) session.auth = HTTPBasicAuth(self.username, self.password) return session @@ -72,7 +81,7 @@ """Simple Token Authentication. Does not adhere to OAuth, simply adds provided token as a header. - :param dict token: Authentication token, must have 'access_token' key. + :param dict[str,str] token: Authentication token, must have 'access_token' key. """ def __init__(self, token): @@ -87,13 +96,18 @@ """ pass - def signed_session(self): + def signed_session(self, session=None): """Create requests session with any required auth headers applied. - :rtype: requests.Session. + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - session = super(BasicTokenAuthentication, self).signed_session() + session = super(BasicTokenAuthentication, self).signed_session(session) header = "{} {}".format(self.scheme, self.token['access_token']) session.headers['Authorization'] = header return session @@ -101,50 +115,62 @@ class OAuthTokenAuthentication(BasicTokenAuthentication): """OAuth Token Authentication. + Requires that supplied token contains an expires_in field. :param str client_id: Account Client ID. - :param dict token: OAuth2 token. + :param dict[str,str] token: OAuth2 token. """ def __init__(self, client_id, token): - self.scheme = 'Bearer' + super(OAuthTokenAuthentication, self).__init__(token) self.id = client_id - self.token = token self.store_key = self.id def construct_auth(self): """Format token header. - :rtype: str. + :rtype: str """ return "{} {}".format(self.scheme, self.token) - def refresh_session(self): + def refresh_session(self, session=None): """Return updated session if token has expired, attempts to refresh using refresh token. - :rtype: requests.Session. + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - return self.signed_session() + return self.signed_session(session) - def signed_session(self): - """Create requests session with any required auth headers - applied. + def signed_session(self, session=None): + """Create requests session with any required auth headers applied. - :rtype: requests.Session. + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - return oauth.OAuth2Session(self.id, token=self.token) + session = session or requests.Session() # Don't call super on purpose, let's "auth" manage the headers. + session.auth = oauth.OAuth2(self.id, token=self.token) + return session class ApiKeyCredentials(Authentication): """Represent the ApiKey feature of Swagger. - Dict should be dict[str, str] to be accepted by requests. + Dict should be dict[str,str] to be accepted by requests. - :param dict[str, str] in_headers: Headers part of the ApiKey - :param dict[str, str] in_query: ApiKey in the query as parameters. + :param dict[str,str] in_headers: Headers part of the ApiKey + :param dict[str,str] in_query: ApiKey in the query as parameters """ def __init__(self, in_headers=None, in_query=None): + super(ApiKeyCredentials, self).__init__() if in_headers is None: in_headers = {} if in_query is None: @@ -156,12 +182,17 @@ self.in_headers = in_headers self.in_query = in_query - def signed_session(self): + def signed_session(self, session=None): """Create requests session with ApiKey. - :rtype: requests.Session. + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session """ - session = super(ApiKeyCredentials, self).signed_session() + session = super(ApiKeyCredentials, self).signed_session(session) session.headers.update(self.in_headers) session.params.update(self.in_query) return session @@ -183,3 +214,21 @@ 'X-BingApis-SDK-Client': 'Python-SDK' } ) + +class TopicCredentials(ApiKeyCredentials): + """Event Grid authentication. + + :param str topic_key: The Event Grid topic key + """ + + _topic_key_header = 'aeg-sas-key' + + def __init__(self, topic_key): + if not topic_key: + raise ValueError("Topic key cannot be None") + super(TopicCredentials, self).__init__( + in_headers={ + self._topic_key_header: topic_key, + } + ) + \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/configuration.py new/msrest-0.4.28/msrest/configuration.py --- old/msrest-0.4.25/msrest/configuration.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/configuration.py 2018-04-18 23:08:15.000000000 +0200 @@ -49,10 +49,10 @@ :param requests.Session session: The session. :param Configuration global_config: The global configuration. - :param dict local_config: The on-the-fly configuration passed on the call. - :param dict kwargs: The current computed values for session.request method. + :param dict[str,str] local_config: The on-the-fly configuration passed on the call. + :param dict[str,str] kwargs: The current computed values for session.request method. :return: Must return kwargs, to be passed to session.request. If None is return, initial kwargs will be used. - :rtype: dict + :rtype: dict[str,str] """ return kwargs @@ -87,6 +87,9 @@ requests.__version__, msrest_version) + # Should we log HTTP requests/response? + self.enable_http_logger = False + # Requests hooks. Must respect requests hook callback signature # Note that we will inject the following parameters: # - kwargs['msrest']['session'] with the current session @@ -94,6 +97,9 @@ self.session_configuration_callback = default_session_configuration_callback + # If set to True, ServiceClient will own the sessionn + self.keep_alive = False + self._config = configparser.ConfigParser() self._config.optionxform = str @@ -102,9 +108,14 @@ @property def user_agent(self): + """The current user agent value.""" return self._user_agent def add_user_agent(self, value): + """Add value to current user agent with a space. + + :param str value: value to add to user agent. + """ self._user_agent = "{} {}".format(self._user_agent, value) def _clear_config(self): @@ -117,7 +128,6 @@ :param str filepath: Path to file where settings will be saved. :raises: ValueError if supplied filepath cannot be written to. - :rtype: None """ sections = [ "Connection", @@ -159,7 +169,6 @@ :param str filepath: Path to existing config file. :raises: ValueError if supplied config file is invalid. - :rtype: None """ try: self._config.read(filepath) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/paging.py new/msrest-0.4.28/msrest/paging.py --- old/msrest-0.4.25/msrest/paging.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/paging.py 2018-04-18 23:08:15.000000000 +0200 @@ -65,6 +65,10 @@ @property def raw(self): + """Get current page as ClientRawResponse. + + :rtype: ClientRawResponse + """ raw = ClientRawResponse(self.current_page, self._response) if self._raw_headers: raw.add_headers(self._raw_headers) @@ -89,6 +93,14 @@ self._current_page_iter_index = 0 def advance_page(self): + """Force moving the cursor to the next azure call. + + This method is for advanced usage, iterator protocol is prefered. + + :raises: StopIteration if no further page + :return: The current page list + :rtype: list + """ if self.next_link is None: raise StopIteration("End of paging") self._current_page_iter_index = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/pipeline.py new/msrest-0.4.28/msrest/pipeline.py --- old/msrest-0.4.25/msrest/pipeline.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/pipeline.py 2018-04-18 23:08:15.000000000 +0200 @@ -46,22 +46,6 @@ class ClientRequest(requests.Request): """Wrapper for requests.Request object.""" - def add_header(self, header, value): - """Add a header to the single request. - - :param str header: The header name. - :param str value: The header value. - """ - self.headers[header] = value - - def add_headers(self, headers): - """Add multiple headers to the single request. - - :param dict headers: A dictionary of headers. - """ - for key, value in headers.items(): - self.add_header(key, value) - def format_parameters(self, params): """Format parameters into a valid query string. It's assumed all parameters have already been quoted as diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/serialization.py new/msrest-0.4.28/msrest/serialization.py --- old/msrest-0.4.25/msrest/serialization.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/serialization.py 2018-04-18 23:08:15.000000000 +0200 @@ -138,10 +138,11 @@ self.additional_properties = {} for k in kwargs: if k not in self._attribute_map: - raise TypeError("{} is not a known attribute of class {}".format(k, self.__class__)) - if k in self._validation and self._validation[k].get("readonly", False): - _LOGGER.warning("Readonly attribute {} will be ignored in class {}".format(k, self.__class__)) - setattr(self, k, kwargs[k]) + _LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__) + elif k in self._validation and self._validation[k].get("readonly", False): + _LOGGER.warning("Readonly attribute %s will be ignored in class %s", k, self.__class__) + else: + setattr(self, k, kwargs[k]) def __eq__(self, other): """Compare objects by comparing all attributes.""" @@ -953,7 +954,8 @@ '{}': self.deserialize_dict } self.deserialize_expected_types = { - 'duration': (isodate.Duration, datetime.timedelta) + 'duration': (isodate.Duration, datetime.timedelta), + 'iso-8601': (datetime.datetime) } self.dependencies = dict(classes) if classes else {} self.key_extractors = [ @@ -1453,7 +1455,7 @@ else: break if len(decimal_str) > 6: - attr = attr.replace(decimal_str, decimal_str[0:-1]) + attr = attr.replace(decimal_str, decimal_str[0:6]) date_obj = isodate.parse_datetime(attr) test_utc = date_obj.utctimetuple() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/service_client.py new/msrest-0.4.28/msrest/service_client.py --- old/msrest-0.4.25/msrest/service_client.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/service_client.py 2018-04-18 23:08:15.000000000 +0200 @@ -46,6 +46,23 @@ _LOGGER = logging.getLogger(__name__) +class SDKClient(object): + """The base class of all generated SDK client. + """ + def __init__(self, creds, config): + self._client = ServiceClient(creds, config) + + def close(self): + """Close the client if keep_alive is True. + """ + self._client.close() + + def __enter__(self): + self._client.__enter__() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self._client.__exit__(exc_type, exc_val, exc_tb) class ServiceClient(object): """REST Service Client. @@ -61,6 +78,22 @@ self.config = config self.creds = creds if creds else Authentication() self._headers = {} + self._session = None + + def __enter__(self): + self.config.keep_alive = True + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + self.config.keep_alive = False + + def close(self): + """Close the session if keep_alive is True. + """ + if self._session: + self._session.close() + self._session = None def _format_data(self, data): """Format field data according to whether it is a stream or @@ -100,35 +133,48 @@ :param requests.Session session: Current request session. :param config: Specific configuration overrides. + :rtype: dict + :return: A dict that will be kwarg-send to session.request """ kwargs = self.config.connection() for opt in ['timeout', 'verify', 'cert']: kwargs[opt] = config.get(opt, kwargs[opt]) - for opt in ['cookies', 'files']: - kwargs[opt] = config.get(opt) + kwargs.update({k:config[k] for k in ['cookies', 'files'] if k in config}) kwargs['allow_redirects'] = config.get( 'allow_redirects', bool(self.config.redirect_policy)) - session.headers.update(self._headers) - session.headers['User-Agent'] = self.config.user_agent - session.headers['Accept'] = 'application/json' - session.max_redirects = config.get( - 'max_redirects', self.config.redirect_policy()) - session.proxies = config.get( - 'proxies', self.config.proxies()) - session.trust_env = config.get( - 'use_env_proxies', self.config.proxies.use_env_settings) - redirect_logic = session.resolve_redirects - - def wrapped_redirect(resp, req, **kwargs): - attempt = self.config.redirect_policy.check_redirect(resp, req) - return redirect_logic(resp, req, **kwargs) if attempt else [] - - session.resolve_redirects = wrapped_redirect - def log_hook(r, *args, **kwargs): - log_request(None, r.request) - log_response(None, r.request, r, result=r) - session.hooks['response'].append(log_hook) + kwargs['headers'] = dict(self._headers) + kwargs['headers']['User-Agent'] = self.config.user_agent + kwargs['headers']['Accept'] = 'application/json' + proxies = config.get('proxies', self.config.proxies()) + if proxies: + kwargs['proxies'] = proxies + + kwargs['stream'] = config.get('stream', True) + + session.max_redirects = config.get('max_redirects', self.config.redirect_policy()) + session.trust_env = config.get('use_env_proxies', self.config.proxies.use_env_settings) + + # Patch the redirect method directly *if not done already* + if not getattr(session.resolve_redirects, 'is_mrest_patched', False): + redirect_logic = session.resolve_redirects + + def wrapped_redirect(resp, req, **kwargs): + attempt = self.config.redirect_policy.check_redirect(resp, req) + return redirect_logic(resp, req, **kwargs) if attempt else [] + wrapped_redirect.is_mrest_patched = True + + session.resolve_redirects = wrapped_redirect + + # if "enable_http_logger" is defined at the operation level, take the value. + # if not, take the one in the client config + # if not, disable http_logger + hooks = [] + if config.get("enable_http_logger", self.config.enable_http_logger): + def log_hook(r, *args, **kwargs): + log_request(None, r.request) + log_response(None, r.request, r, result=r) + hooks.append(log_hook) def make_user_hook_cb(user_hook, session): def user_hook_cb(r, *args, **kwargs): @@ -137,13 +183,15 @@ return user_hook_cb for user_hook in self.config.hooks: - session.hooks['response'].append(make_user_hook_cb(user_hook, session)) + hooks.append(make_user_hook_cb(user_hook, session)) - max_retries = config.get( - 'retries', self.config.retry_policy()) + if hooks: + kwargs['hooks'] = {'response': hooks} + + # Change max_retries in current all installed adapters + max_retries = config.get('retries', self.config.retry_policy()) for protocol in self._protocols: - session.mount(protocol, - requests.adapters.HTTPAdapter(max_retries=max_retries)) + session.adapters[protocol].max_retries=max_retries output_kwargs = self.config.session_configuration_callback(session, self.config, config, **kwargs) if output_kwargs is not None: @@ -151,7 +199,7 @@ return kwargs - def send_formdata(self, request, headers=None, content=None, stream=True, **config): + def send_formdata(self, request, headers=None, content=None, **config): """Send data as a multipart form-data request. We only deal with file-like objects or strings at this point. The requests is not yet streamed. @@ -159,7 +207,6 @@ :param ClientRequest request: The request object to be sent. :param dict headers: Any headers to add to the request. :param dict content: Dictionary of the fields of the formdata. - :param bool stream: Is the session in stream mode. True by default for compat. :param config: Any specific config overrides. """ if content is None: @@ -169,35 +216,44 @@ if content_type and content_type.lower() == 'application/x-www-form-urlencoded': # Do NOT use "add_content" that assumes input is JSON request.data = {f: d for f, d in content.items() if d is not None} - return self.send(request, headers, None, stream=stream, **config) + return self.send(request, headers, None, **config) else: # Assume "multipart/form-data" file_data = {f: self._format_data(d) for f, d in content.items() if d is not None} - return self.send(request, headers, None, files=file_data, stream=stream, **config) + return self.send(request, headers, None, files=file_data, **config) - def send(self, request, headers=None, content=None, stream=True, **config): + def send(self, request, headers=None, content=None, **config): """Prepare and send request object according to configuration. :param ClientRequest request: The request object to be sent. :param dict headers: Any headers to add to the request. :param content: Any body data to add to the request. - :param bool stream: Is the session in stream mode. True by default for compat. :param config: Any specific config overrides """ - response = None - session = self.creds.signed_session() + if self.config.keep_alive and self._session is None: + self._session = requests.Session() + try: + session = self.creds.signed_session(self._session) + except TypeError: # Credentials does not support session injection + session = self.creds.signed_session() + if self._session is not None: + _LOGGER.warning("Your credentials class does not support session injection. Performance will not be at the maximum.") + kwargs = self._configure_session(session, **config) - kwargs['stream'] = stream + if headers: + request.headers.update(headers) - request.add_headers(headers if headers else {}) if not kwargs.get('files'): request.add_content(content) - try: + if request.data: + kwargs['data']=request.data + kwargs['headers'].update(request.headers) + response = None + try: try: response = session.request( - request.method, request.url, - data=request.data, - headers=request.headers, + request.method, + request.url, **kwargs) return response @@ -208,12 +264,14 @@ try: session = self.creds.refresh_session() - kwargs = self._configure_session(session) + kwargs = self._configure_session(session, **config) + if request.data: + kwargs['data']=request.data + kwargs['headers'].update(request.headers) response = session.request( - request.method, request.url, - request.data, - request.headers, + request.method, + request.url, **kwargs) return response except (oauth2.rfc6749.errors.InvalidGrantError, @@ -226,8 +284,15 @@ msg = "Error occurred in request." raise_with_traceback(ClientRequestError, msg, err) finally: - if not response or not stream: - session.close() + self._close_local_session_if_necessary(response, session, kwargs['stream']) + + def _close_local_session_if_necessary(self, response, session, stream): + # Do NOT close session if session is self._session. No exception. + if self._session is session: + return + # Here, it's a local session, I might close it. + if not response or not stream: + session.close() def stream_download(self, data, callback): """Generator for streaming request body data. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest/version.py new/msrest-0.4.28/msrest/version.py --- old/msrest-0.4.25/msrest/version.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/msrest/version.py 2018-04-18 23:08:15.000000000 +0200 @@ -24,5 +24,5 @@ # # -------------------------------------------------------------------------- - -msrest_version = "0.4.25" +#: version of this package. Use msrest.__version__ instead +msrest_version = "0.4.28" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest.egg-info/PKG-INFO new/msrest-0.4.28/msrest.egg-info/PKG-INFO --- old/msrest-0.4.25/msrest.egg-info/PKG-INFO 2018-01-08 22:52:45.000000000 +0100 +++ new/msrest-0.4.28/msrest.egg-info/PKG-INFO 2018-04-18 23:08:55.000000000 +0200 @@ -1,14 +1,13 @@ Metadata-Version: 1.1 Name: msrest -Version: 0.4.25 +Version: 0.4.28 Summary: AutoRest swagger generator Python client runtime. Home-page: https://github.com/Azure/msrest-for-python Author: Microsoft Corporation Author-email: UNKNOWN License: MIT License -Description-Content-Type: UNKNOWN Description: AutoRest: Python Client Runtime - ================================ + =============================== .. image:: https://travis-ci.org/Azure/msrest-for-python.svg?branch=master :target: https://travis-ci.org/Azure/msrest-for-python @@ -29,6 +28,49 @@ Release History --------------- + 2018-04-18 Version 0.4.28 + +++++++++++++++++++++++++ + + **Features** + + - msrest is now able to keep the "requests.Session" alive for performance. To activate this behavior: + + - Use the final Client as a context manager (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and `client.close()` (requires generation with Autorest.Python 3.0.50 at least) + - Use `client.config.keep_alive = True` and client._client.close() (not recommended, but available in old releases of SDK) + + - All Authentication classes now define `signed_session` and `refresh_session` with an optional `session` parameter. + To take benefits of the session improvement, a subclass of Authentication *MUST* add this optional parameter + and use it if it's not `None`: + + def signed_session(self, session=None): + session = session or requests.Session() + + # As usual from here. + + 2018-03-07 Version 0.4.27 + +++++++++++++++++++++++++ + + **Features** + + - Disable HTTP log by default (security), add `enable_http_log` to restore it #86 + + **BugFixes** + + - Fix incorrect date parsing if ms precision is over 6 digits #82 + + 2018-01-30 Version 0.4.26 + +++++++++++++++++++++++++ + + **Features** + + - Add TopicCredentials for EventGrid client + + **Bugfixes** + + - Fix minimal dependency of isodate + - Fix serialisation from dict if datetime provided + 2018-01-08 Version 0.4.25 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/msrest.egg-info/requires.txt new/msrest-0.4.28/msrest.egg-info/requires.txt --- old/msrest-0.4.25/msrest.egg-info/requires.txt 2018-01-08 22:52:45.000000000 +0100 +++ new/msrest-0.4.28/msrest.egg-info/requires.txt 2018-04-18 23:08:55.000000000 +0200 @@ -1,6 +1,6 @@ requests~=2.14 requests_oauthlib>=0.5.0 -isodate>=0.5.4 +isodate>=0.6.0 certifi>=2017.4.17 [:python_version<'3.4'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.4.25/setup.py new/msrest-0.4.28/setup.py --- old/msrest-0.4.25/setup.py 2018-01-08 22:52:05.000000000 +0100 +++ new/msrest-0.4.28/setup.py 2018-04-18 23:08:15.000000000 +0200 @@ -28,7 +28,7 @@ setup( name='msrest', - version='0.4.25', + version='0.4.28', author='Microsoft Corporation', packages=find_packages(exclude=["tests", "tests.*"]), url=("https://github.com/Azure/msrest-for-python"), @@ -49,7 +49,7 @@ install_requires=[ "requests~=2.14", "requests_oauthlib>=0.5.0", - "isodate>=0.5.4", + "isodate>=0.6.0", "certifi>=2017.4.17", ], extras_require={
