Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add minimal client implementation for Feeds API #73

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
88716eb
feat: add feeds api with examples and wrapper files
Giriharan219 Oct 16, 2024
074f782
feat: separte function for query feeds
Giriharan219 Oct 16, 2024
590d91c
docs: Update doc strings
Giriharan219 Oct 17, 2024
f4f06e0
fix: Update upload mulitple package function
Giriharan219 Oct 17, 2024
5d80d06
fix: errors due to mypy checks
Giriharan219 Oct 21, 2024
7dda9c7
docs: Update rst files for auth and feeds client
Giriharan219 Oct 21, 2024
785eb39
fix: Update file names and client name for feeds client
Giriharan219 Oct 21, 2024
8392e0b
feat: add pytest for feeds and auth apis
Giriharan219 Oct 22, 2024
d90ab93
fix: mypy and black issues
Giriharan219 Oct 23, 2024
facf591
fix: remove hardcoded workspace in pytest for feeds
Giriharan219 Oct 23, 2024
c8aa6eb
docs: update api ref rst file
Giriharan219 Oct 23, 2024
37ebd69
docs: update getting started rst file
Giriharan219 Oct 23, 2024
5d41864
fix: err due to invalid path in getting started.rst file
Giriharan219 Oct 23, 2024
11beed3
fix: remove unwanted helpers
Giriharan219 Oct 24, 2024
0690f73
fix: Address self review comments
Giriharan219 Oct 24, 2024
734429b
docs: alignment in the rst files
Giriharan219 Oct 24, 2024
480e410
fix: address second set of self review comments
Giriharan219 Oct 24, 2024
1c01493
docs: Update doc string of auth models
Giriharan219 Oct 24, 2024
fc06d3a
feat: add delete feed api
Giriharan219 Oct 24, 2024
76bccbc
fix: issues due to linting
Giriharan219 Oct 24, 2024
c046b1a
docs: update rst files
Giriharan219 Oct 24, 2024
c9bd9bb
fix: remove auth implementation
Giriharan219 Oct 25, 2024
77e9f18
fix: address some of the PR comments
Giriharan219 Oct 25, 2024
570843e
fix: address rest of the PR comments
Giriharan219 Oct 30, 2024
7d65312
fix: address self review comments
Giriharan219 Oct 30, 2024
3ea0521
fix: error due to del feed with invalid id
Giriharan219 Oct 30, 2024
99320ba
fix: mypy issues due to incompatible types
Giriharan219 Oct 30, 2024
8efc6de
fix: improvement PR comments
Giriharan219 Nov 2, 2024
cb30e6d
fix: mypy issue due to var type incompatibility
Giriharan219 Nov 2, 2024
8edf916
fix: update self review comments
Giriharan219 Nov 4, 2024
552c39d
fix: issue due to pipeline failure
Giriharan219 Nov 4, 2024
6dfb17e
docs: update the doc with new api for upload feed
Giriharan219 Nov 4, 2024
05e9dcc
fix: address another set of review comments
Giriharan219 Nov 5, 2024
5e0752d
fix: pytest failure due to invalid assertion
Giriharan219 Nov 5, 2024
6b7f2a1
fix: address self review comments
Giriharan219 Nov 5, 2024
26af9a6
fix: issue due to black formatter
Giriharan219 Nov 5, 2024
33c80fb
fix: pipeline failure issue
Giriharan219 Nov 5, 2024
44472b7
fix: address self review comments
Giriharan219 Nov 5, 2024
da58c28
fix: pipeline failure
Giriharan219 Nov 5, 2024
75bef43
fix: address final PR comments
Giriharan219 Nov 7, 2024
14b1401
fix: issue due to black formatter
Giriharan219 Nov 7, 2024
4f683f9
fix: update response models
Giriharan219 Nov 7, 2024
db529c8
fix: update feeds model with some fixes
Giriharan219 Nov 7, 2024
f639d77
docs: update utility doc string
Giriharan219 Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ API Reference
api_reference/dataframe
api_reference/spec
api_reference/file
api_reference/feeds

Indices and tables
------------------
Expand Down
18 changes: 18 additions & 0 deletions docs/api_reference/feeds.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.. _api_tag_page:

nisystemlink.clients.feeds
======================

.. autoclass:: nisystemlink.clients.feeds.FeedsClient
:exclude-members: __init__

.. automethod:: __init__
.. automethod:: create_feed
.. automethod:: query_feeds
.. automethod:: upload_package
.. automethod:: upload_package_content
.. automethod:: delete_feed

.. automodule:: nisystemlink.clients.feeds.models
:members:
:imported-members:
41 changes: 39 additions & 2 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ Update and Delete Specifications
:language: python
:linenos:


File API
-------

Expand All @@ -183,4 +182,42 @@ Get the metadata of a File using its Id and download it.

.. literalinclude:: ../examples/file/download_file.py
:language: python
:linenos:
:linenos:

Feeds API
-------

Overview
~~~~~~~~

The :class:`.FeedsClient` class is the primary entry point of the Feeds API.

When constructing a :class:`.FeedsClient`, you can pass an
:class:`.HttpConfiguration` (like one retrieved from the
:class:`.HttpConfigurationManager`), or let :class:`.FeedsClient` use the
default connection. The default connection depends on your environment.

With a :class:`.FeedsClient` object, you can:

* Get the list of feeds, create feed, upload package to feed and delete feed.

Examples
~~~~~~~~

Create a new feed.

.. literalinclude:: ../examples/feeds/create_feed.py
:language: python
:linenos:

Query feeds and upload a package to feed.

.. literalinclude:: ../examples/feeds/query_and_upload_feeds.py
:language: python
:linenos:

Delete a feed.

.. literalinclude:: ../examples/feeds/delete_feed.py
:language: python
:linenos:
40 changes: 40 additions & 0 deletions examples/feeds/create_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Functionality of creating feeds APIs."""

from nisystemlink.clients.core import ApiException, HttpConfiguration
from nisystemlink.clients.feeds._feeds_client import FeedsClient
from nisystemlink.clients.feeds.models import (
CreateFeedRequest,
Platform,
)

# Update the constants.
FEED_NAME = ""
FEED_DESCRIPTION = ""
PLATFORM = Platform.WINDOWS
WORKSPACE_ID = (
None # None uses Default workspace. Replace with Systemlink workspace id.
)

server_url = "" # SystemLink API URL
server_api_key = "" # SystemLink API key

# Provide the valid API key and API URL for client initialization.
client = FeedsClient(HttpConfiguration(api_key=server_api_key, server_uri=server_url))

# Creating Feeds.
try:
feed_request = CreateFeedRequest(
name=FEED_NAME,
description=FEED_DESCRIPTION,
platform=PLATFORM,
workspace=WORKSPACE_ID,
)
feed_details = client.create_feed(feed=feed_request)

print("Feed created Successfully.")
print(f"Created feed details: {feed_details}")

except ApiException as exp:
print(exp)
except Exception as exp:
print(exp)
36 changes: 36 additions & 0 deletions examples/feeds/delete_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Functionality of deleting feed API."""

from nisystemlink.clients.core import ApiException, HttpConfiguration
from nisystemlink.clients.feeds._feeds_client import FeedsClient
from nisystemlink.clients.feeds.models import Platform
from nisystemlink.clients.feeds.utilities import get_feed_by_name

# Update the constants.
FEED_NAME = ""
PLATFORM = Platform.WINDOWS
WORKSPACE_ID = (
None # None uses Default workspace. Replace with Systemlink workspace id.
)

server_url = "" # SystemLink API URL
server_api_key = "" # SystemLink API key

# Provide the valid API key and API URL for client initialization.
client = FeedsClient(HttpConfiguration(api_key=server_api_key, server_uri=server_url))

# Deleting Feed.
try:
# Get ID of the Feed to delete by name
feeds = client.query_feeds(platform=PLATFORM, workspace=WORKSPACE_ID)
feed = get_feed_by_name(feeds=feeds, name=FEED_NAME)
feed_id = feed.id if feed else None

# Delete the Feed by ID
if feed_id:
client.delete_feed(id=feed_id)
print("Feed deleted successfully.")

except ApiException as exp:
print(exp)
except Exception as exp:
print(exp)
44 changes: 44 additions & 0 deletions examples/feeds/query_and_upload_feeds.py
Giriharan219 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Functionality of uploading & querying feeds APIs."""

from nisystemlink.clients.core import ApiException, HttpConfiguration
from nisystemlink.clients.feeds._feeds_client import FeedsClient
from nisystemlink.clients.feeds.models import Platform
from nisystemlink.clients.feeds.utilities import get_feed_by_name

# Update the constants.
FEED_NAME = ""
PLATFORM = None
FEED_DESCRIPTION = ""
PLATFORM = Platform.WINDOWS
WORKSPACE_ID = (
None # None uses Default workspace. Replace with Systemlink workspace id.
)
PACKAGE_PATH = ""

server_url = "" # SystemLink API URL
server_api_key = "" # SystemLink API key

# Provide the valid API key and API URL for client initialization.
client = FeedsClient(HttpConfiguration(api_key=server_api_key, server_uri=server_url))

# To upload a package to feed.
try:
# Get ID of the Feed to upload by name
feeds = client.query_feeds(platform=PLATFORM, workspace=WORKSPACE_ID)
feed = get_feed_by_name(feeds=feeds, name=FEED_NAME)
feed_id = feed.id if feed else None

# Upload the package to Feed by ID
if feed_id:
client.upload_package(
feed_id=feed_id,
overwrite=True,
package_file_path=PACKAGE_PATH,
)
print("Package uploaded sucessfully.")

except ApiException as exp:
print(exp)

except Exception as exp:
print(exp)
3 changes: 3 additions & 0 deletions nisystemlink/clients/feeds/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ._feeds_client import FeedsClient

# flake8: noqa
190 changes: 190 additions & 0 deletions nisystemlink/clients/feeds/_feeds_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
"""Implementation of SystemLink Feeds Client."""

from typing import BinaryIO, List, Optional

from nisystemlink.clients import core
from nisystemlink.clients.core._uplink._base_client import BaseClient
from nisystemlink.clients.core._uplink._methods import delete, get, post
from uplink import Part, Path, Query

from . import models


class FeedsClient(BaseClient):
def __init__(self, configuration: Optional[core.HttpConfiguration] = None):
"""Initialize an instance.

Args:
configuration: Defines the web server to connect to and information about
how to connect. If not provided, the
:class:`HttpConfigurationManager <nisystemlink.clients.core.HttpConfigurationManager>`
is used to obtain the configuration.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
if configuration is None:
configuration = core.HttpConfigurationManager.get_configuration()

super().__init__(configuration, base_path="/nifeed/v1/")

@post("feeds")
def create_feed(self, feed: models.CreateFeedRequest) -> models.Feed:
"""Create a new feed with the provided feed details.

Args:
feeds (models.CreateFeedsRequest): Request to create the feed.

Returns:
models.Feed: Details of the created feed.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
...

@get("feeds", args=[Query, Query])
def __query_feeds(
self,
platform: Optional[str] = None,
Giriharan219 marked this conversation as resolved.
Show resolved Hide resolved
workspace: Optional[str] = None,
) -> models.QueryFeedsResponse:
"""Lists available feeds for the Platform `platform` under the Workspace `workspace`.

Args:
platform (Optional[str]): Information about system platform. Defaults to None.
workspace (Optional[str]): Workspace id. Defaults to None.

Returns:
models.QueryFeedsResponse: List of feeds.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
...

def query_feeds(
self,
platform: Optional[models.Platform] = None,
workspace: Optional[str] = None,
) -> List[models.Feed]:
"""Lists available feeds for the Platform `platform` under the Workspace `workspace`.

Args:
platform (Optional[models.Platform]): Information about system platform. \
Defaults to None.
workspace (Optional[str]): Workspace id. Defaults to None.

Returns:
List[models.Feed]: List of feeds.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
platform_by_str = platform.value if platform is not None else None
response = self.__query_feeds(
platform=platform_by_str,
workspace=workspace,
).feeds

return response

@post(
"feeds/{feedId}/packages",
args=[Path(name="feedId"), Query(name="ShouldOverwrite")],
)
def __upload_package(
self,
feed_id: str,
package: Part,
overwrite: Query = False,
) -> models.Package:
"""Upload package to SystemLink feed.

Args:
feed_id (str): ID of the feed.
package (Part): Package file to be uploaded.
overwrite (Query): Set to True, to overwrite the package if it already exists.\
Defaults to False.

Returns:
models.Package: Uploaded package information.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
...

def upload_package(
Giriharan219 marked this conversation as resolved.
Show resolved Hide resolved
self,
feed_id: str,
package_file_path: str,
overwrite: bool = False,
) -> models.Package:
"""Upload package to SystemLink feed.

Args:
feed_id (str): ID of the feed.
package_file_path (str): File path of the package to be uploaded.
overwrite (bool): Set to True, to overwrite the package if it already exists.\
Defaults to False.

Returns:
models.Package: Uploaded package information.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
response = self.__upload_package(
feed_id=feed_id,
overwrite=overwrite,
package=open(package_file_path, "rb"),
)

return response

def upload_package_content(
self,
feed_id: str,
package: BinaryIO,
overwrite: bool = False,
) -> models.Package:
"""Upload package to SystemLink feed.

Args:
feed_id (str): ID of the feed.
package (BinaryIO): Package file to be uploaded.
overwrite (bool): Set to True, to overwrite the package if it already exists.\
Defaults to False.

Returns:
models.Package: Uploaded package information.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
response = self.__upload_package(
feed_id=feed_id,
overwrite=overwrite,
package=package,
)

return response

@delete(
"feeds/{feedId}",
args=[Path(name="feedId")],
)
def delete_feed(self, id: str) -> None:
"""Delete feed and its packages.

Args:
id (str): ID of the feed to be deleted.

Returns:
None.

Raises:
ApiException: if unable to communicate with the Feeds Service.
"""
...
Loading