Skip to content

Commit

Permalink
Release v0.4.0 (#10)
Browse files Browse the repository at this point in the history
* chore: bump version refs to `0.4.0`

* feat: add client method for regulated markets search + update tests and docs

* chore: tweak project TOML

* refactor: API base URL to include current API version + related updates
  • Loading branch information
sr-murthy authored Dec 10, 2024
1 parent aa196fe commit 61379a2
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 24 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ and the [CodeQL Analysis YML](https://github.com/sr-murthy/fsrapiclient/blob/mai

## Versioning and Releases

The [PyPI package](https://pypi.org/project/fsrapiclient/) is currently at version `0.3.0`.
The [PyPI package](https://pypi.org/project/fsrapiclient/) is currently at version `0.4.0`.

There is currently no dedicated pipeline for releases - both [GitHub releases](https://github.com/sr-murthy/fsrapiclient/releases) and [PyPI packages](https://pypi.org/project/fsrapiclient) are published manually, but both have the same version tag.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

A lightweight Python client library for the UK [Financial Services Register](https://register.fca.org.uk/s/) [RESTful API](https://register.fca.org.uk/Developer/s/).

The [PyPI package](https://pypi.org/project/fsrapiclient) is currently at version `0.3.0`.
The [PyPI package](https://pypi.org/project/fsrapiclient) is currently at version `0.4.0`.

The Financial Services Register, or FS Register, is a **public** database of all firms, individuals, funds, and other entities, that are either currently, or have been previously, authorised and/or regulated by the UK [Financial Conduct Authority (FCA)](https://www.fca.org.uk) and/or the [Prudential Regulation Authority (PRA)](http://bankofengland.co.uk/pra).

Expand Down
2 changes: 1 addition & 1 deletion docs/sources/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ and the `CodeQL Analysis YML <https://github.com/sr-murthy/fsrapiclient/blob/mai
Versioning and Releases :fas:`upload`
=====================================

The `PyPI package <https://pypi.org/project/fsrapiclient/>`_ is currently at version ``0.3.0``.
The `PyPI package <https://pypi.org/project/fsrapiclient/>`_ is currently at version ``0.4.0``.

There is currently no dedicated pipeline for releases - both `GitHub releases <https://github.com/sr-murthy/fsrapiclient/releases>`_ and `PyPI packages <https://pypi.org/project/fsrapiclient>`_ are published manually, but both have the same version tag.

Expand Down
28 changes: 17 additions & 11 deletions docs/sources/fs-register-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ There are three main categories of resource about which information can be reque
- **individuals** - individuals associated with the type of firms described above, either current or past. Individuals in the register have unique **individual reference numbers (IRN)** and their endpoints usually take these as one of the parameters. They are described in more detail :ref:`here <fs-register-api.individual-requests>`.
- **funds** - investment funds or collective investment schemes (CIS),including subfunds of funds. Funds in the register have unique **product reference numbers (PRN)** and their endpoints usually take these as one of the parameters. They are described in more detail :ref:`here <fs-register-api.fund-requests>`.

There is also a **common search** API endpoint that allows a search for any of these resources by a name substring and a corresponding type specification (firm, individual, or fund). This is described in more detail :ref:`here <fs-register-api.common-search-requests>`.
There are also search endpoints that allow a search for *(a)* any of these resources by a name substring and a corresponding type specification (firm, individual, or fund), or *(b)* `regulated markets <https://www.handbook.fca.org.uk/handbook/glossary/G978.html?date=2007-01-20>`_. These are described in more detail :ref:`here <fs-register-api.common-search-requests>`.

.. _fs-register-api.request-headers:

Expand Down Expand Up @@ -189,58 +189,64 @@ The common search API endpoint is a parameterised search endpoint which is summa
* - API Endpoint
- Request Method
- Search Parameters
* - ``/V0.1/CommonSearch``
* - ``/V0.1/Search``
- GET
- ``q`` (resource name), ``type`` (resource type - ``'firm'``, ``'individual'``, or ``'fund'``)

Requests should be of the form:

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=resource_name&type=resource_type HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=resource_name&type=resource_type HTTP/1.1
For example, here are a few valid common search requests.

* Common search for Barclays Bank Plc (FRN #122702):

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=Barclays+Bank+plc&type=firm HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=Barclays+Bank+plc&type=firm HTTP/1.1
* Common search for Hastings Insurance Services Limited (FRN #311492)

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=hastings+insurance+services&type=firm HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=hastings+insurance+services&type=firm HTTP/1.1
* Common search for all Natwest-related firms:

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=Natwest&type=firm HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=Natwest&type=firm HTTP/1.1
* Common search for a specific individual, Mark Carney (IRN #MXC29012):

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=mark+carney&type=individual HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=mark+carney&type=individual HTTP/1.1
* Common search for a generic individual name "John Smith", with multiple results:

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=John+Smith&type=individual HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=John+Smith&type=individual HTTP/1.1
* Common search for a specific fund, Jupiter Asia Pacific Income (PRN #635641):

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=jupiter+asia+pacific+income&type=fund HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=jupiter+asia+pacific+income&type=fund HTTP/1.1
* Common search for a specific fund, abrdn Multi-Asset Fund (PRN #637980):

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=abrdn+multi-asset+fund&type=fund HTTP/1.1
GET https://register.fca.org.uk/services/V0.1/Search?q=abrdn+multi-asset+fund&type=fund HTTP/1.1
For details and examples on calling this endpoint via this library see :ref:`this <usage.common-search>`.
One particular type of common search-based endpoint that the API provides separately is for `regulated markets <https://www.handbook.fca.org.uk/handbook/glossary/G978.html?date=2007-01-20>`_. These are special markets which are regulated by UK and/or EU/EEA financial legislation. API requests for regulated markets should look as below:

.. code:: http
GET https://register.fca.org.uk/services/V0.1/CommonSearch?q=RM HTTP/1.1
For details and examples on calling these endpoint via this library see :ref:`this <usage.common-search>`.
44 changes: 43 additions & 1 deletion docs/sources/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The common search endpoint can be used via the :py:meth:`~fsrapiclient.api.FsrAp

.. code:: bash
q=<resource name>&type=<resource type>
q=resource_name&type=resource_type
where ``q`` is a parameter whose value should be the name (or name substring) of a resource (firm, individual, or fund), and ``type`` is a parameter whose value should be one of ``'firm'``, ``'individual'``, ``'fund'``.

Expand Down Expand Up @@ -127,6 +127,48 @@ The response data as stored in the :py:attr:`~fsrapiclient.api.FsrApiResponse.fs
>>> client.common_search(urlencode({'q': 'natwest', 'type': 'individual'})).fsr_data
# Null
.. _usage.regulated-markets:

Regulated Markets
-----------------

The client implements a `regulated markets <https://www.handbook.fca.org.uk/handbook/glossary/G978.html?date=2007-01-20>`_ search endpoint via the :py:meth:`~fsrapiclient.api.FsrApiClient.get_regulated_markets` method:

.. code:: python
>>> c.get_regulated_markets().fsr_data
[{'Name': 'The London Metal Exchange',
'TradingName': '',
'Type of business or Individual': 'Exchange - RM',
'Reference Number': '',
'Status': '',
'FirmURL': 'https://register.fca.org.uk/services/V0.1/Firm/'},
{'Name': 'ICE Futures Europe',
'TradingName': '',
'Type of business or Individual': 'Exchange - RM',
'Reference Number': '',
'Status': '',
'FirmURL': 'https://register.fca.org.uk/services/V0.1/Firm/'},
{'Name': 'London Stock Exchange',
'TradingName': '',
'Type of business or Individual': 'Exchange - RM',
'Reference Number': '',
'Status': '',
'FirmURL': 'https://register.fca.org.uk/services/V0.1/Firm/'},
{'Name': 'Aquis Stock Exchange Limited',
'TradingName': 'ICAP Securities & Derivatives Exchange Limited',
'Type of business or Individual': 'Exchange - RM',
'Reference Number': '',
'Status': '',
'FirmURL': 'https://register.fca.org.uk/services/V0.1/Firm/'},
{'Name': 'Cboe Europe Equities Regulated Market',
'TradingName': '',
'Type of business or Individual': 'Exchange - RM',
'Reference Number': '',
'Status': '',
'FirmURL': 'https://register.fca.org.uk/services/V0.1/Firm/'}]
.. _usage.searching-ref-numbers:

Searching for FRNs, IRNs and PRNs
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ keywords = [
"financial services",
"financial services register",
"prudential regulation authority",
"regulated markets",
"restful api",
"uk",
]
Expand Down
2 changes: 1 addition & 1 deletion src/fsrapiclient/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "0.3.0"
__version__ = "0.4.0"

84 changes: 80 additions & 4 deletions src/fsrapiclient/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def common_search(self, search_str: str) -> FsrApiResponse:
>>> client.common_search(urlencode({'q': 'Hastings Direct', 'type': 'firm'}))
<Response [200]>
"""
url = f'{FSR_API_CONSTANTS.BASEURL.value}/{self.api_version}/Search?{search_str}'
url = f'{FSR_API_CONSTANTS.BASEURL.value}/Search?{search_str}'

try:
return FsrApiResponse(self.api_session.get(url))
Expand All @@ -352,7 +352,7 @@ def _search_ref_number(self, resource_name: str, resource_type: str) -> str:
/V0.1/Search?q=resource_name&type=resource_type
to perform a case-insensitive search for resources of type
``resource_type``in the FS Register on the given resource name
``resource_type`` in the FS Register on the given resource name
substring.
Returns a non-null string of the resource ref. number if there is
Expand Down Expand Up @@ -564,8 +564,6 @@ def _get_resource_info(self, resource_ref_number: str, resource_type: str, modif
url = (
f'{FSR_API_CONSTANTS.BASEURL.value}'
'/'
f'{self.api_version}'
'/'
f'{resource_endpoint_base}'
'/'
f'{resource_ref_number}'
Expand Down Expand Up @@ -1518,6 +1516,84 @@ def get_fund_subfunds(self, prn: str) -> FsrApiResponse:
modifiers=('Subfund',)
)

def get_regulated_markets(self) -> FsrApiResponse:
""":py:class:`~fsrapiclient.api.FsrApiResponse` : Returns a response containing details of all current regulated markets, as defined in UK and EU / EEA financial services legislation.
For further information consult the API documentation:
https://register.fca.org.uk/Developer/s/
or the FCA glossary:
https://www.handbook.fca.org.uk/handbook/glossary/G978.html?date=2007-01-20
Returns
-------
FsrApiResponse
Wrapper of the API response object - there may be no data in
the response if the common search query produces no results.
Examples
--------
>>> import json, os
>>> client = FsrApiClient(os.environ['API_USERNAME'], os.environ['API_KEY'])
>>> res = client.get_regulated_markets()
>>> print(json.dumps(res.fsr_data, indent=True))
[
{
"Name": "The London Metal Exchange",
"TradingName": "",
"Type of business or Individual": "Exchange - RM",
"Reference Number": "",
"Status": "",
"FirmURL": "https://register.fca.org.uk/services/V0.1/Firm/"
},
{
"Name": "ICE Futures Europe",
"TradingName": "",
"Type of business or Individual": "Exchange - RM",
"Reference Number": "",
"Status": "",
"FirmURL": "https://register.fca.org.uk/services/V0.1/Firm/"
},
{
"Name": "London Stock Exchange",
"TradingName": "",
"Type of business or Individual": "Exchange - RM",
"Reference Number": "",
"Status": "",
"FirmURL": "https://register.fca.org.uk/services/V0.1/Firm/"
},
{
"Name": "Aquis Stock Exchange Limited",
"TradingName": "ICAP Securities & Derivatives Exchange Limited",
"Type of business or Individual": "Exchange - RM",
"Reference Number": "",
"Status": "",
"FirmURL": "https://register.fca.org.uk/services/V0.1/Firm/"
},
{
"Name": "Cboe Europe Equities Regulated Market",
"TradingName": "",
"Type of business or Individual": "Exchange - RM",
"Reference Number": "",
"Status": "",
"FirmURL": "https://register.fca.org.uk/services/V0.1/Firm/"
}
]
"""
url = (
f'{FSR_API_CONSTANTS.BASEURL.value}'
'/'
'CommonSearch'
'?'
f'{urlencode({"q": "RM"})}'
)

return FsrApiResponse(
self.api_session.get(url)
)

if __name__ == "__main__": # pragma: no cover
# Doctest the module from the project root using
#
Expand Down
6 changes: 3 additions & 3 deletions src/fsrapiclient/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ class FSR_API_CONSTANTS(Enum):
Examples
--------
>>> FSR_API_CONSTANTS.BASEURL.value
'https://register.fca.org.uk/services'
>>> FSR_API_CONSTANTS.API_VERSION.value
'V0.1'
>>> FSR_API_CONSTANTS.BASEURL.value
'https://register.fca.org.uk/services/V0.1'
>>> FSR_API_CONSTANTS.RESOURCE_TYPES.value
{'firm': {'type_name': 'firm', 'endpoint_base': 'Firm'}, 'fund': {'type_name': 'fund', 'endpoint_base': 'CIS'}, 'individual': {'type_name': 'individual', 'endpoint_base': 'Individuals'}}
"""

BASEURL = 'https://register.fca.org.uk/services'
API_VERSION = 'V0.1'
BASEURL = f'https://register.fca.org.uk/services/{API_VERSION}'
RESOURCE_TYPES = {
'firm': {'type_name': 'firm', 'endpoint_base': 'Firm'},
'fund': {'type_name': 'fund', 'endpoint_base': 'CIS'},
Expand Down
13 changes: 13 additions & 0 deletions tests/units/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,16 @@ def test_fsr_api_client__get_fund_subfunds(self):
recv_response = test_client.get_fund_subfunds('1234567890')
assert recv_response.ok
assert not recv_response.fsr_data

def test_fsr_api_client__get_regulated_markets(self):
test_client = FsrApiClient(self._api_username, self._api_key)

# Covers the regulated markets API endpoint, which ATM returns a
# list of markets regulated by UK and/or EU/EEA financial legislation.
#
# We don't bother to check the exact list of markets returned by the
# endpoint, as this may change - it is enough to check that the endpoint
# should provide some data.
recv_response = test_client.get_regulated_markets()
assert recv_response.ok
assert recv_response.fsr_data
2 changes: 1 addition & 1 deletion tests/units/test_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
class TestFsrApiConstants:

def test_fsr_api_constants(self):
assert FSR_API_CONSTANTS.BASEURL.value == 'https://register.fca.org.uk/services'
assert FSR_API_CONSTANTS.API_VERSION.value == 'V0.1'
assert FSR_API_CONSTANTS.BASEURL.value == 'https://register.fca.org.uk/services/V0.1'
assert FSR_API_CONSTANTS.RESOURCE_TYPES.value == {
'firm': {'type_name': 'firm', 'endpoint_base': 'Firm'},
'fund': {'type_name': 'fund', 'endpoint_base': 'CIS'},
Expand Down

0 comments on commit 61379a2

Please sign in to comment.