Skip to main content

Python client for FileMaker Web APIs.

Project description

``pgfm``: a Python client for FileMaker Server Web APIs
============================================================

:version: ``pgfm`` 0.7.3, July 25, 2023.
:contact: Mikhail Edoshin

The |pgfm| module is a Python client for |FileMaker|_ Server Web APIs. It aims to support all FileMaker APIs in a unified and transparent manner.

.. warning:: This is a work in progress. The current version supports the XML
API, both old and new formats. It does not yet fully support container
fields, and layout information in ``FMPXMLLAYOUT`` format and the whole
Data API. Another thing in progress are user and developer documentation.

Sample usage
------------

A FileMaker server at ``http://fm.example.com`` hosts a file **Sample** with toy orders:

.. figure:: https://github.com/MikhailEdoshin/pgfm/raw/main/res/figure-1.png
:scale: 75

The schema of the **Sample** file and a layout to fetch data.

We need to write backend code that receives a customer ID, requests all orders of that customer from FileMaker along with their most recent event, and returns them back to the caller as a JSON object with the following structure::

{ type: "customerOrders" customerId
orders: [
{ orderId statusTime statusName
items: [
{ productId productName price quantity } ] } ] }

To support that a FileMaker developer added a layout **Web.Orders**. The layout does a good half of the work to shape the result: it defines the fields that will be returned and arranges things so that the fields from the **Event** table show the most recent event.

To use the layout the backend needs send a search request to this layout, get back the result, and process the data to rearrange them as required. With |Pgfm| the simplest way to achieve that would look so:

.. _snippet:

.. code:: Python

import pgfm

def customerOrders(customerId):
# -> customerId: customer ID, int.
# <- result, list, JSON-compatible.
res = dict(type="customerOrders", customerId=customerId, orders=[])
usr = pgfm.User("username", "********")
srv = pgfm.Srv("https://fm.example.com/", usr)
req = pgfm.ReqLaySel() \
.db("Sample") \
.lay("Web.Orders") \
.col("customerId", customerId) \
.sort("Event::time", "descend")
for rec in srv.send(req).read():
order = dict(
orderId = rec.col("id"),
statusTime = rec.col("Event::time").toPyDatetime().isoformat(),
statusName = rec.col("Event::type"),
items = [])
res.orders.append(order)
for row in rec.rel("OrderItem"):
order.items.append(dict(
productId = row.col("productId"),
productName = row.col("Product::name"),
price = row.col("Product::price"),
quantity = row.col("quantity")))
return res

The ``res`` is the resulting object. The ``usr`` is the account we use to send the request and ``srv`` is the FileMaker server. The ``req`` is a request: something like a form that describes the desired action. Here we are going to ask the server to search for records (``ReqLaySel``) and specify the necessary details: file, layout and search criteria.

We also specify we want to get the results sorted by the **Event::time** field. Although the layout is set up to show the last event, the sort command will sort the orders by their first event. In our case it is fine, but generally it is one of specific FileMaker things one has to intimately understand.

We send the request to the server and immediately read the response. The result is an iterable of records so we also immediately start iterating over them. If something goes wrong with an HTTP request or a FileMaker response the code will automatically raise an exception.

For each record we create a new ``dict`` (``order``) and fill it with data from the record’s fields. The module reads FileMaker field values as string-like objects that can be safely used in any string context. By default they will be formatted according to FileMaker rules: for example, a date would come out as ``M/D/Y``. They are not really strings though; they know their specific type and expose methods to correctly convert their values into other representations. In our case we want to format the timestamps according to ISO 8601, so we convert them first to a Python ``datetime`` and then format the result with ``isoformat()``.

We also add a list for order items. Then we get a portal to the **OrderItem** table, loop through its rows, for each row create another ``dict`` and immediately place it into the ``items`` list.

In the end we return the result. We used only ``list`` and ``dict`` instances and FileMaker values are strings, so the result can be safely serialized into JSON.

License
-------

The module is available under the MIT license. The data used for the examples in the documentation are dervied from a sample database from |Contoso|_.

Usage
-----

The module uses third-party libraries ``lxml`` and ``requests``. The source code is available on GitHub_. The author, Mikhail Edoshin, can be reached there or via email: one_, another_.

.. _GitHub: https://github.com/MikhailEdoshin/pgfm/
.. _one: mikhail.edoshin@proofgeist.com
.. _another: mikhail.edoshin@mail.ru

Development
-----------

The project contains the following files::

/
|_ LICENSE -- licence (MIT)
|_ Makefile -- Makefile; run 'make' to see help
|_ README.rst -- The 'README' file (this one)
|_ pyproject.toml -- Python package specification
|_ requirements.txt -- Python requirements.
|_ res\
| |_ figure-1.png -- resources for 'README'
|_ src\
| |_ pgfm.py -- the module
|_ tests\
|_ test.py -- tests


Use ``Makefile`` to set up the virtual environment for interactive use and tests. The Python package is built with ``flit``.

.. References

.. |Contoso| replace:: one of Microsoft projects (licensed under MIT)
.. _Contoso: https://github.com/microsoft/Windows-appsample-customers-orders-d
atabase

.. |FileMaker| replace:: FileMaker
.. _FileMaker: https://www.claris.com/filemaker/

.. |Pgfm| replace:: ``pgfm``

.. |Pip| replace:: ``pip``

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pgfm-0.7.3.tar.gz (102.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pgfm-0.7.3-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file pgfm-0.7.3.tar.gz.

File metadata

  • Download URL: pgfm-0.7.3.tar.gz
  • Upload date:
  • Size: 102.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.3

File hashes

Hashes for pgfm-0.7.3.tar.gz
Algorithm Hash digest
SHA256 62014b07269994781d9a07d6e09fa91a7016fe13da351fd46503b8692051e8b9
MD5 7772ae7553a36982eba310183e9a7ae2
BLAKE2b-256 a32c278ce6bd97bacff9a7997a8e946f697243d8cf633862302dafdbf8d07582

See more details on using hashes here.

File details

Details for the file pgfm-0.7.3-py3-none-any.whl.

File metadata

  • Download URL: pgfm-0.7.3-py3-none-any.whl
  • Upload date:
  • Size: 33.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.3

File hashes

Hashes for pgfm-0.7.3-py3-none-any.whl
Algorithm Hash digest
SHA256 63b880f577cd85563389d3fbf21bbb437795dad2a8ecbe9af071bf164b5f1f35
MD5 ea484ed4adb9db9963ae282fb774556f
BLAKE2b-256 6eef7656f819a380bba1f03434188401d628fa4cbf9a5b18e0f00e3294c402c6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page