From d6b5a14afc4296c355d8e39f66e41ed38b9a27ca Mon Sep 17 00:00:00 2001 From: Andy Chase Date: Wed, 10 Jun 2026 12:01:45 -0400 Subject: [PATCH] Add default timeout and getter for last response --- fmrest.egg-info/PKG-INFO | 15 +++++++++--- fmrest.egg-info/SOURCES.txt | 1 + fmrest/dataAPI/__init__.py | 46 ++++++++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/fmrest.egg-info/PKG-INFO b/fmrest.egg-info/PKG-INFO index 488baff..bc7a2d9 100644 --- a/fmrest.egg-info/PKG-INFO +++ b/fmrest.egg-info/PKG-INFO @@ -1,4 +1,4 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.4 Name: fmrest Version: 1.1.2 Summary: a Python library for interacting with the FileMaker REST APIs @@ -6,11 +6,20 @@ Home-page: https://github.com/eluce2/fmrest Author: Eric Luce Author-email: eluce@huntington.edu License: MIT -Description: UNKNOWN Keywords: filemaker helper rest api fmrest fmapi -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Natural Language :: English Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Utilities +License-File: LICENSE.txt +Requires-Dist: requests +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: home-page +Dynamic: keywords +Dynamic: license +Dynamic: license-file +Dynamic: requires-dist +Dynamic: summary diff --git a/fmrest.egg-info/SOURCES.txt b/fmrest.egg-info/SOURCES.txt index 6807af1..45ed93f 100644 --- a/fmrest.egg-info/SOURCES.txt +++ b/fmrest.egg-info/SOURCES.txt @@ -1,3 +1,4 @@ +LICENSE.txt README.md setup.cfg setup.py diff --git a/fmrest/dataAPI/__init__.py b/fmrest/dataAPI/__init__.py index 60b7752..c62f974 100644 --- a/fmrest/dataAPI/__init__.py +++ b/fmrest/dataAPI/__init__.py @@ -4,12 +4,16 @@ Special Thanks to Andrew Wolfe for the initial build of this class. ''' -import requests, json -from requests.auth import HTTPBasicAuth +import json +from typing import Union + +import requests import urllib3 +from requests.auth import HTTPBasicAuth -class DataAPIv1: +class DataAPIv1: + """FileMaker Server 17 or later Data API v1 client""" def __init__(self, server, secure=True): self._api_url = 'https://' + server + '/fmi/data/v1/databases' self._return_data = [] @@ -18,6 +22,7 @@ def __init__(self, server, secure=True): self._api_key = None self.solution = None self.secure = secure + self._last_response: Union[requests.Response, None] = None if not self.secure: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -110,8 +115,11 @@ def _build_custom_response(self, data=None): return response - def _request(self, method, verb, layout='', record_id='', query_params={}, data=None, auth=None, containerURL='', file=''): - """ Makes a Filemaker API call and returns the response as an array.""" + def _request(self, method, verb, layout='', record_id='', query_params=None, data=None, auth=None, containerURL='', file='', timeout=(5,30)): + """Makes a Filemaker API call and returns the response as an array.""" + + if query_params is None: + query_params = {} if not self.solution: self.errorCode = -1 @@ -156,32 +164,35 @@ def _request(self, method, verb, layout='', record_id='', query_params={}, data= self.data_sent = data_json self.url = url - test_url = 'https://webhook.site/b540812c-f488-482e-a153-d22e8c6fddb4' + # test_url = 'https://webhook.site/b540812c-f488-482e-a153-d22e8c6fddb4' + req: Union[requests.Response, None] = None try: - req = '' # complete the request if verb == "get": req = requests.get(url, headers=headers, params=query_params, - verify=self.secure) + verify=self.secure, timeout=timeout) elif verb == "post": if auth: - req = requests.post(url, data=data_json, headers=headers, auth=auth, verify=self.secure) + req = requests.post(url, data=data_json, headers=headers, auth=auth, verify=self.secure, timeout=timeout) elif method == "container": - req = requests.post(url, files={'upload': file}, headers=headers, verify=self.secure) + req = requests.post(url, files={'upload': file}, headers=headers, verify=self.secure, timeout=timeout) else: req = requests.post(url, data=data_json, headers=headers, - verify=self.secure) + verify=self.secure, timeout=timeout) elif verb == "patch": req = requests.patch(url, data=data_json, headers=headers, - verify=self.secure) + verify=self.secure, timeout=timeout) elif verb == "delete": - req = requests.delete(url, headers=headers, verify=self.secure) + req = requests.delete(url, headers=headers, verify=self.secure, timeout=timeout) except Exception as e: self.errorCode = -3 - self.errorMessage = "Could not connect to server: " + str(req) + "\n" + str(e) + self.errorMessage = f"Could not connect to server: {str(req) if req else ''}\n{str(e)}" return self._build_custom_response() + # Store the last response + self._last_response = req + try: req = req.json() self.errorCode = int(req['messages'][0]['code']) @@ -191,3 +202,10 @@ def _request(self, method, verb, layout='', record_id='', query_params={}, data= self.errorCode = -2 self.errorMessage = "Unexpected response from server: " + str(req) return self._build_custom_response() + + @property + def last_response(self) -> Union[requests.Response, None]: + """The :py:class:`requests.Response` object for the most recent request + (or `None` if not available.) + """ + return self._last_response