From d42a7784dd0eb243d419f18d4c6704ac3853b976 Mon Sep 17 00:00:00 2001 From: TagShelf <32621192+tagshelf@users.noreply.github.com> Date: Tue, 14 May 2024 19:32:21 -0400 Subject: [PATCH 1/5] chore(master): release 0.4.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 42 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0967ef4..8efb275 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{} +{".":"0.4.0"} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b654edc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +## [0.4.0](https://github.com/tagshelfsrl/alfred-python/compare/v0.3.0...v0.4.0) (2024-05-14) + + +### Features + +* add job domain ([#9](https://github.com/tagshelfsrl/alfred-python/issues/9)) ([aa9528c](https://github.com/tagshelfsrl/alfred-python/commit/aa9528c18d35c2789fcda0590a7f270a691bc8f5)) +* Add LICENSE and pyproject.toml configuration ([#1](https://github.com/tagshelfsrl/alfred-python/issues/1)) ([e674ba6](https://github.com/tagshelfsrl/alfred-python/commit/e674ba62777ea05fb5b0ebf4ed91c578dd3a02fa)) +* **AL-860:** Implement base HTTP client class ([#3](https://github.com/tagshelfsrl/alfred-python/issues/3)) ([da0d92e](https://github.com/tagshelfsrl/alfred-python/commit/da0d92e19b7279f18eec918195f5ca76bc1f09c7)) +* **AL-866:** Implement authentication methods supported in Alfred ([#4](https://github.com/tagshelfsrl/alfred-python/issues/4)) ([25c1530](https://github.com/tagshelfsrl/alfred-python/commit/25c153060129b73ef8a0511c28b98c5471905dee)) +* **AL-867:** Implement OAuth refresh token handler ([#5](https://github.com/tagshelfsrl/alfred-python/issues/5)) ([adc29d5](https://github.com/tagshelfsrl/alfred-python/commit/adc29d5562bf74dec97b3428e4dcb8bebfd201f5)) +* **AL-869:** Implemented Data Points domain ([#6](https://github.com/tagshelfsrl/alfred-python/issues/6)) ([faf0d09](https://github.com/tagshelfsrl/alfred-python/commit/faf0d09995d7a2ad563f7145c4e7c4b7395d367a)) +* **AL-870:** implement session domain ([#7](https://github.com/tagshelfsrl/alfred-python/issues/7)) ([823afa0](https://github.com/tagshelfsrl/alfred-python/commit/823afa0b415411cd4a0a824291ca3565676f54cf)) +* **AL-871:** Implement Files domain class and methods ([#14](https://github.com/tagshelfsrl/alfred-python/issues/14)) ([f34469d](https://github.com/tagshelfsrl/alfred-python/commit/f34469d8a0647691fc139da35bcc0376e3785651)) +* AL-886 enables pypi publishes ([#20](https://github.com/tagshelfsrl/alfred-python/issues/20)) ([85abecb](https://github.com/tagshelfsrl/alfred-python/commit/85abecb051e6304ccbf92f47ebc6834572df5880)) +* introduce response parsing based on configurable option at instance and endpoint level. ([#11](https://github.com/tagshelfsrl/alfred-python/issues/11)) ([cc0995d](https://github.com/tagshelfsrl/alfred-python/commit/cc0995d9e66c5ed4dc84761a1212d1c6d0ae6119)) +* setup functionality to apply throttling when the remaining requests get to a certain threshold. ([#15](https://github.com/tagshelfsrl/alfred-python/issues/15)) ([bceb818](https://github.com/tagshelfsrl/alfred-python/commit/bceb818570094daf258eb15ca5592047ec9f2808)) +* Update README documentation ([#12](https://github.com/tagshelfsrl/alfred-python/issues/12)) ([4724ddb](https://github.com/tagshelfsrl/alfred-python/commit/4724ddb82111be4f7ffa8ee08767cd81306a57b0)) + + +### Bug Fixes + +* adds missing permissions to publish job ([#23](https://github.com/tagshelfsrl/alfred-python/issues/23)) ([5884a24](https://github.com/tagshelfsrl/alfred-python/commit/5884a24c2803fc3f81250602036f27fd4720768b)) +* adds missing trailing slash ([3d5fb17](https://github.com/tagshelfsrl/alfred-python/commit/3d5fb17e72f692983122389e79e415e4195de875)) +* adds pypi test url for staging deployments ([495db8a](https://github.com/tagshelfsrl/alfred-python/commit/495db8a1159b7a2d9b82fcaa094330bf3bda1365)) +* **AL-869:** Set overrides as empty dict if value is None ([#8](https://github.com/tagshelfsrl/alfred-python/issues/8)) ([c446c89](https://github.com/tagshelfsrl/alfred-python/commit/c446c89ef0ca5f2152e1041ec5a007b7f89eae9e)) +* branch check and prod pypi url ([a6c6e64](https://github.com/tagshelfsrl/alfred-python/commit/a6c6e64bc30c6b432ec9faf06e6bee154b06c461)) +* Fixed bad imports ([#17](https://github.com/tagshelfsrl/alfred-python/issues/17)) ([ac4afbd](https://github.com/tagshelfsrl/alfred-python/commit/ac4afbdce6f0ded162d5fe5196a5d5804de9cc91)) +* prerelease-type set value to beta ([89178db](https://github.com/tagshelfsrl/alfred-python/commit/89178db752611b2e3e88f770bab60942a16f4bdf)) +* pypi wrong upload urls ([2181ece](https://github.com/tagshelfsrl/alfred-python/commit/2181eced8aa262a0f9bb6398d0711c2516fbe8b3)) +* trigger build ([e41149a](https://github.com/tagshelfsrl/alfred-python/commit/e41149a396a509a5e981887f410820c7cb6f5616)) +* trying to enable prerelease tags ([7b33846](https://github.com/tagshelfsrl/alfred-python/commit/7b33846b69d848b5032d23d7216cc190b79c2203)) +* trying to enable prerelease tags 2 ([fa998cd](https://github.com/tagshelfsrl/alfred-python/commit/fa998cd78bde051b097b9ebcb220f1b810de59c2)) +* trying to enable prereleases adding directly to action ([b332af1](https://github.com/tagshelfsrl/alfred-python/commit/b332af17bda35f80e88315892550ce56bf426017)) +* typo on github actions permissions ([4f8a49e](https://github.com/tagshelfsrl/alfred-python/commit/4f8a49e6f3270d59fe3d93ce6c335cf362d4108a)) +* ues old release-please-action until they finish changes ([#24](https://github.com/tagshelfsrl/alfred-python/issues/24)) ([8b039ae](https://github.com/tagshelfsrl/alfred-python/commit/8b039ae176d70cafc2d6037bd3c573973ad51900)) +* Updated domain methods to expect a tuple instead of a Response object ([#16](https://github.com/tagshelfsrl/alfred-python/issues/16)) ([6f28402](https://github.com/tagshelfsrl/alfred-python/commit/6f284020611c99fc4b2482b25fc51fe783cf37ac)) +* use old release-please ([577c888](https://github.com/tagshelfsrl/alfred-python/commit/577c888e97f4593f5477d80b7f95393acd49e9a4)) +* Use response headers to get the content-type instead of request ([#13](https://github.com/tagshelfsrl/alfred-python/issues/13)) ([e54eeab](https://github.com/tagshelfsrl/alfred-python/commit/e54eeab7bc32736210106b65b4c766cf9fe5133f)) +* versioning strategy adjustment ([55fa551](https://github.com/tagshelfsrl/alfred-python/commit/55fa551f812bdb3525bfa6f500c0b6f5a0585119)) +* versioning strategy config ([823d7c0](https://github.com/tagshelfsrl/alfred-python/commit/823d7c0cc86bcb07b896cfae29a806b5dab4aad0)) diff --git a/pyproject.toml b/pyproject.toml index fe626b0..940ba4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "alfred-python" -version = "0.0.1" +version = "0.4.0" authors = [{ name = "Tagshelf LLC", email = "support@tagshelf.com" }] description = "Python library designed to simplify and streamline interactions with the Alfred API" readme = "README.md" From 1b0d070932db0d46bef20546a78bdb70a4ccebf4 Mon Sep 17 00:00:00 2001 From: Mateh Elismar <31004078+MatehElismar@users.noreply.github.com> Date: Thu, 16 May 2024 08:49:17 -0400 Subject: [PATCH 2/5] feat: implement realtime functionality. (#18) * feat: implement realtime functionality. * docs: add docstring to class methods. - refactor: rename socket client to not reflect the protocol. * fix: add ConnectionError exception. * chore: change debug message for established connection. * chore: add websocket-client dependency to pyproject.toml. * docs: add realtime section to readme.md. * fix: make private methods "private" * fix: initialize logger inside AlfredRealtimeClient so it can log important stages of the connection. * fix: replace custom events with specific supported events. --- README.md | 85 +++++++++++++++++++- pyproject.toml | 2 + requirements.txt | 7 ++ src/alfred/base/config.py | 4 +- src/alfred/base/constants.py | 86 +++++++++++++++++++++ src/alfred/exceptions/__init__.py | 7 ++ src/alfred/realtime/__init__.py | 124 ++++++++++++++++++++++++++++++ src/alfred/typings/misc.py | 4 +- 8 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 src/alfred/exceptions/__init__.py create mode 100644 src/alfred/realtime/__init__.py diff --git a/README.md b/README.md index d6404a0..663a0ce 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Check out this simple example to get up and running: from alfred.rest import AlfredClient from alfred.base.config import Configuration -config = Configuration.v1() +config = Configuration.default() auth_config = {"api_key": "AXXXXXXXXXXXXXXXXXXXXXX"} client = AlfredClient(config, auth_config) @@ -171,6 +171,89 @@ In this SDK, we implement automatic retries to enhance the reliability of networ For non-idempotent methods like POST and PATCH, the SDK does not perform retries by default because doing so could potentially result in unwanted side effects or duplicate operations. If you need to enable retries for these methods under specific circumstances, please handle them cautiously in your application logic. +## Real-time Events + +The `alfred-python` library provides a way to listen to events emitted by Alfred IPA in real-time through a websockets implementation. This feature is particularly useful when you need to monitor the progress of a Job, File, or any other event that occurs within the Alfred platform. To see more information visit our [official documentation](https://docs.tagshelf.dev). + +### Getting started + +To get started, you need to create an instance of the `AlfredRealTimeClient` class. + +```python +from src.alfred.realtime import AlfredRealTimeClient +from src.alfred.base.config import Configuration +from src.alfred.http.typed import AuthConfiguration + +config = Configuration.default() + +auth_config = AuthConfiguration({ + "api_key": "AXXXXXXXXXXXXXXXXXXXXXX" +}) + +client = AlfredRealTimeClient(config, auth_config, verbose=True) +``` + +### File Events +These events are specifically designed to respond to a variety of actions or status changes related to Files. To see more details about File events, visit our [official documentation](https://docs.tagshelf.dev/event-api/fileevents). +```python +# Listen to all File events +client.on_file_event(lambda data: print(data)) +``` + +### Job Events +Alfred performs asynchronous document classification, extraction, and indexing on a variety of file types. The events detailed here offer insights into how a Job progresses, fails, retries, or completes its tasks. To see more details about Job events, visit our [official documentation](https://docs.tagshelf.dev/event-api/jobevents). + +```python +# Listen to all Job events +client.on_job_event(lambda data: print(data)) +``` + +### Specific Events + +This enables you to select a specific event you wish to monitor from the list of supported events. +It's particularly useful when you want to listen to a specific event instead of all events of a particular type. + +Here's an example of how to listen to a specific event: + +```python +from src.alfred.base.constants import FileEvent, JobEvent + +# Listen to the specific File Done event +client.on(FileEvent.FILE_DONE_EVENT.value, lambda data: print(data)) + +# Listen to the specific Job Finished event +client.on(JobEvent.JOB_FINISHED_EVENT.value, lambda data: print(data)) +``` + +Here is a list of all supported events: + +| Event Type | Event Name | Description | +| --- | --- | --- | +| FileEvent | `FILE_ADD_TO_JOB_EVENT` | Triggered when a file is added to a job for processing. | +| FileEvent | `FILE_CATEGORY_CREATE_EVENT` | Occurs when a new category is created for a file. | +| FileEvent | `FILE_CATEGORY_DELETE_EVENT` | Signals the deletion of a file's category. | +| FileEvent | `FILE_CHANGE_TAG_EVENT` | Indicates a change in the tag associated with a file. | +| FileEvent | `FILE_DONE_EVENT` | Marks the completion of file processing. | +| FileEvent | `FILE_EXTRACTED_DATA_CREATE_EVENT` | Triggered when new data is extracted from a file. | +| FileEvent | `FILE_EXTRACTED_DATA_DELETE_EVENT` | Occurs when extracted data from a file is deleted. | +| FileEvent | `FILE_FAILED_EVENT` | Indicates a failure in file processing. | +| FileEvent | `FILE_MOVE_EVENT` | Signals the movement of a file within the system. | +| FileEvent | `FILE_MOVE_TO_PENDING_EVENT` | Triggered when a file is moved to a pending state. | +| FileEvent | `FILE_MOVE_TO_RECYCLE_BIN_EVENT` | Indicates movement of a file to the recycle bin. | +| FileEvent | `FILE_PROPERTY_CREATE_EVENT` | Reflects the creation of a file property. | +| FileEvent | `FILE_PROPERTY_DELETE_EVENT` | Signals the deletion of a file property. | +| FileEvent | `FILE_REMOVE_TAG_EVENT` | Signals the removal of a tag from a file. | +| FileEvent | `FILE_STATUS_UPDATE_EVENT` | Indicates an update in the file's status. | +| FileEvent | `FILE_UPDATE_EVENT` | Triggered when a file is updated in any manner. | +| JobEvent | `JOB_CREATE_EVENT` | Triggered when a new job is instantiated for file operations. | +| JobEvent | `JOB_EXCEEDED_RETRIES_EVENT` | Fires when job exceeds maximum retry attempts for a stage. | +| JobEvent | `JOB_FAILED_EVENT` | Occurs when a job halts due to an unrecoverable error. | +| JobEvent | `JOB_FINISHED_EVENT` | Triggered when job successfully completes all workflow stages. | +| JobEvent | `JOB_INVALID_EVENT` | Fires when job fails initial validation of input files or parameters. | +| JobEvent | `JOB_RETRY_EVENT` | Triggered when job retries a stage after a recoverable failure. | +| JobEvent | `JOB_STAGE_UPDATE_EVENT` | Occurs when job transitions from one workflow stage to another. | +| JobEvent | `JOB_START_EVENT` | Triggered when job begins its workflow and state machine. | + ## Development Setup ### Setting up the development environment diff --git a/pyproject.toml b/pyproject.toml index 940ba4e..d15deab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,8 @@ dependencies = [ "pydantic >= 2.0", "pydantic-settings >= 2.0", "requests >= 2.30", + "python-socketio >= 5.11", + "websocket-client >= 1.8" ] [project.urls] diff --git a/requirements.txt b/requirements.txt index c0657b0..4c78517 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,9 @@ annotated-types==0.6.0 +bidict==0.23.1 build==1.2.1 certifi==2024.2.2 charset-normalizer==3.3.2 +h11==0.14.0 idna==3.7 importlib_metadata==7.1.0 packaging==24.0 @@ -10,8 +12,13 @@ pydantic-settings==2.2.1 pydantic_core==2.18.2 pyproject_hooks==1.1.0 python-dotenv==1.0.1 +python-engineio==4.9.0 +python-socketio==5.11.2 requests==2.31.0 +simple-websocket==1.0.0 tomli==2.0.1 typing_extensions==4.11.0 urllib3==2.2.1 +websocket-client==1.8.0 +wsproto==1.2.0 zipp==3.18.1 diff --git a/src/alfred/base/config.py b/src/alfred/base/config.py index d834023..5bafaa0 100644 --- a/src/alfred/base/config.py +++ b/src/alfred/base/config.py @@ -4,6 +4,7 @@ class ConfigurationDict(TypedDict): base_url: Text + realtime_url: Text version: int @@ -15,7 +16,7 @@ class Configuration: @staticmethod def default() -> ConfigurationDict: """ - Returns default client configuration. Currently targets Alfred V1. + Returns default client configuration. Currently, targets Alfred V1. """ return Configuration.v1() @@ -28,4 +29,5 @@ def v1(overrides: Optional[OverridesDict] = None) -> ConfigurationDict: return { "version": 1, "base_url": overrides.get("base_url", "https://app.tagshelf.com"), + "realtime_url": overrides.get("realtime_url", "https://sockets.tagshelf.io"), } diff --git a/src/alfred/base/constants.py b/src/alfred/base/constants.py index 41b6108..30f4609 100644 --- a/src/alfred/base/constants.py +++ b/src/alfred/base/constants.py @@ -1,3 +1,5 @@ +from enum import Enum + from src.alfred.http.typed import ResponseType # Response type/header mapping @@ -6,3 +8,87 @@ ResponseType.TEXT: "text/plain", ResponseType.XML: "application/xml", } + + +class EventType(Enum): + """ + Enumeration of event types. + """ + JOB_EVENT = "job_event" + FILE_EVENT = "file_event" + + +class FileEvent(Enum): + # Triggered when a file is added to a job for processing. + FILE_ADD_TO_JOB_EVENT = "file_add_to_job_event" + + # Occurs when a new category is created for a file. + FILE_CATEGORY_CREATE_EVENT = "file_category_create_event" + + # Signals the deletion of a file's category. + FILE_CATEGORY_DELETE_EVENT = "file_category_delete_event" + + # Indicates a change in the tag associated with a file. + FILE_CHANGE_TAG_EVENT = "file_change_tag_event" + + # Marks the completion of file processing. + FILE_DONE_EVENT = "file_done_event" + + # Triggered when new data is extracted from a file. + FILE_EXTRACTED_DATA_CREATE_EVENT = "file_extracted_data_create_event" + + # Occurs when extracted data from a file is deleted. + FILE_EXTRACTED_DATA_DELETE_EVENT = "file_extracted_data_delete_event" + + # Indicates a failure in file processing. + FILE_FAILED_EVENT = "file_failed_event" + + # Signals the movement of a file within the system. + FILE_MOVE_EVENT = "file_move_event" + + # Triggered when a file is moved to a pending state. + FILE_MOVE_TO_PENDING_EVENT = "file_move_to_pending_event" + + # Indicates movement of a file to the recycle bin. + FILE_MOVE_TO_RECYCLE_BIN_EVENT = "file_move_to_recycle_bin_event" + + # Reflects the creation of a file property. + FILE_PROPERTY_CREATE_EVENT = "file_property_create_event" + + # Signals the deletion of a file property. + FILE_PROPERTY_DELETE_EVENT = "file_property_delete_event" + + # Signals the removal of a tag from a file. + FILE_REMOVE_TAG_EVENT = "file_remove_tag_event" + + # Indicates an update in the file's status. + FILE_STATUS_UPDATE_EVENT = "file_status_update_event" + + # Triggered when a file is updated in any manner. + FILE_UPDATE_EVENT = "file_update_event" + + +class JobEvent(Enum): + # Triggered when a new job is instantiated for file operations. + JOB_CREATE_EVENT = "job_create_event" + + # Fires when job exceeds maximum retry attempts for a stage. + JOB_EXCEEDED_RETRIES_EVENT = "job_exceeded_retries_event" + + # Occurs when a job halts due to an unrecoverable error. + JOB_FAILED_EVENT = "job_failed_event" + + # Triggered when job successfully completes all workflow stages. + JOB_FINISHED_EVENT = "job_finished_event" + + # Fires when job fails initial validation of input files or parameters. + JOB_INVALID_EVENT = "job_invalid_event" + + # Triggered when job retries a stage after a recoverable failure. + JOB_RETRY_EVENT = "job_retry_event" + + # Occurs when job transitions from one workflow stage to another. + JOB_STAGE_UPDATE_EVENT = "job_stage_update_event" + + # Triggered when job begins its workflow and state machine. + JOB_START_EVENT = "job_start_event" diff --git a/src/alfred/exceptions/__init__.py b/src/alfred/exceptions/__init__.py new file mode 100644 index 0000000..446f135 --- /dev/null +++ b/src/alfred/exceptions/__init__.py @@ -0,0 +1,7 @@ +class ConnectionError(Exception): + """ + Raised when a connection error occurs. + """ + def __init__(self, message="A connection error occurred"): + self.message = message + super().__init__(self.message) diff --git a/src/alfred/realtime/__init__.py b/src/alfred/realtime/__init__.py new file mode 100644 index 0000000..0894dec --- /dev/null +++ b/src/alfred/realtime/__init__.py @@ -0,0 +1,124 @@ +# Native Imports +from typing import Union + +# 3rd Party Imports +import socketio + +# Project Imports +import src.alfred.exceptions +from src.alfred.base.config import ConfigurationDict +from src.alfred.base.constants import EventType, FileEvent, JobEvent +from src.alfred.http.typed import AuthConfiguration +from src.alfred.utils import logging, setup_logger + + +class AlfredRealTimeClient: + def __init__(self, config: ConfigurationDict, auth_config: AuthConfiguration, verbose=False): + """ + Initializes the AlfredRealTimeClient class. + + Args: + config (ConfigurationDict): The configuration dictionary. + auth_config (AuthConfiguration): The authentication configuration. + verbose (bool, optional): Whether to print verbose output. Defaults to False. + """ + self.socket = socketio.Client() + self.verbose = verbose + self.config = config + self.auth_config = auth_config + self.base_url = config.get("realtime_url") + + # Initialize logger + self.logger = logging.getLogger("alfred-python") + if self.logger.level == logging.NOTSET: + setup_logger({ + "level": "DEBUG" if verbose else "INFO", + "name": "alfred-python" + }) + print(self.logger.level) + + # Subscribe to connection life-cycle events. + self.socket.on('connect', self.__on_connect) + self.socket.on('disconnect', self.__on_disconnect) + self.socket.on('connect_error', self.__on_connect_error) + + # Establish connection with verbose output if enabled + if self.verbose: + self.logger.debug("Attempting to establish a connection...") + try: + self.socket.connect(f"{self.base_url}?apiKey={auth_config.get('api_key')}") + except Exception as err: + raise src.alfred.exceptions.ConnectionError(f"Could not establish connection with server: {err}") + + def __on_connect(self): + """ + Handles the 'connect' event. + """ + self.logger.info(f"Successfully connected to: {self.base_url}") + + def __on_disconnect(self): + """ + Handles the 'disconnect' event. + """ + self.logger.info("Disconnected from the server.") + + def __on_connect_error(self, err): + """ + Handles the 'connect_error' event. + + Args: + err (str): The error message. + """ + self.logger.info("Connection error: %s", err) + self.disconnect() + raise Exception(f"Failed to connect to {self.base_url}: {err}") + + def __callback(self, event: Union[FileEvent, JobEvent, EventType], callback): + """ + Wrapper function to subscribe a specific event. + + Args: + event (str): The event name. + callback (function): The callback function to handle the event. + """ + def handle_event(data): + if self.verbose: + self.logger.debug(f"Event {event} received: %s", data) + callback(data) + + self.socket.on(event, handle_event) + + def on_file_event(self, callback): + """ + Listens to all file-related events. + + Args: + callback (function): The callback function to handle the event. + """ + self.__callback(EventType.FILE_EVENT.value, callback) + + def on_job_event(self, callback): + """ + Listens to all job-related events. + + Args: + callback (function): The callback function to handle the event. + """ + self.__callback(EventType.JOB_EVENT.value, callback) + + def on(self, event: Union[FileEvent, JobEvent], callback): + """ + Listens to a specific event. + + Args: + event (str): The event name. + callback (function): The callback function to handle the event. + """ + self.__callback(event, callback) + + def disconnect(self): + """ + Disconnects client from the server. + """ + self.logger.info("Closing connection...") + self.socket.disconnect() diff --git a/src/alfred/typings/misc.py b/src/alfred/typings/misc.py index 90a4920..b855fab 100644 --- a/src/alfred/typings/misc.py +++ b/src/alfred/typings/misc.py @@ -1,10 +1,10 @@ # Native imports -from typing import TypedDict +from typing import TypedDict, Union # Typed dictionaries class LoggingOptions(TypedDict): - level: int + level: Union[str, int] name: str format: str papertrail_host: str From fa5a8452b573ea09c1ea66438b84082f257a727f Mon Sep 17 00:00:00 2001 From: Mateh Elismar <31004078+MatehElismar@users.noreply.github.com> Date: Mon, 20 May 2024 14:04:57 -0400 Subject: [PATCH 3/5] fix: move the alfred package up in the hierarchy out of the src/ folder. (#36) * fix: move the alfred package up in the hierarchy out of the src/ folder. * move files from /src to root directory. * fix import references. * update pyproject.toml file. * chore: remove __version__ variable form lib root. --- Makefile | 4 ++-- README.md | 10 +++++----- alfred/__init__.py | 1 + {src/alfred => alfred}/base/__init__.py | 0 {src/alfred => alfred}/base/config.py | 0 {src/alfred => alfred}/base/constants.py | 2 +- {src/alfred => alfred}/base/exceptions.py | 0 {src/alfred => alfred}/exceptions/__init__.py | 0 {src/alfred => alfred}/http/__init__.py | 0 {src/alfred => alfred}/http/http_client.py | 0 {src/alfred => alfred}/http/typed.py | 0 {src/alfred => alfred}/realtime/__init__.py | 12 ++++++------ {src/alfred => alfred}/rest/__init__.py | 14 +++++++------- .../alfred => alfred}/rest/data_points/__init__.py | 0 {src/alfred => alfred}/rest/data_points/base.py | 0 {src/alfred => alfred}/rest/data_points/v1.py | 4 ++-- {src/alfred => alfred}/rest/files/__init__.py | 0 {src/alfred => alfred}/rest/files/base.py | 0 {src/alfred => alfred}/rest/files/typed.py | 0 {src/alfred => alfred}/rest/files/v1.py | 7 +++---- {src/alfred => alfred}/rest/jobs/__init__.py | 0 {src/alfred => alfred}/rest/jobs/base.py | 2 +- {src/alfred => alfred}/rest/jobs/typed.py | 0 {src/alfred => alfred}/rest/jobs/v1.py | 6 +++--- {src/alfred => alfred}/rest/sessions/__init__.py | 0 {src/alfred => alfred}/rest/sessions/base.py | 0 {src/alfred => alfred}/rest/sessions/v1.py | 4 ++-- alfred/typings/__init__.py | 1 + {src/alfred => alfred}/typings/misc.py | 0 alfred/utils/__init__.py | 1 + {src/alfred => alfred}/utils/logging.py | 2 +- pyproject.toml | 1 - src/alfred/__init__.py | 1 - src/alfred/typings/__init__.py | 1 - src/alfred/utils/__init__.py | 1 - 35 files changed, 36 insertions(+), 38 deletions(-) create mode 100644 alfred/__init__.py rename {src/alfred => alfred}/base/__init__.py (100%) rename {src/alfred => alfred}/base/config.py (100%) rename {src/alfred => alfred}/base/constants.py (98%) rename {src/alfred => alfred}/base/exceptions.py (100%) rename {src/alfred => alfred}/exceptions/__init__.py (100%) rename {src/alfred => alfred}/http/__init__.py (100%) rename {src/alfred => alfred}/http/http_client.py (100%) rename {src/alfred => alfred}/http/typed.py (100%) rename {src/alfred => alfred}/realtime/__init__.py (91%) rename {src/alfred => alfred}/rest/__init__.py (83%) rename {src/alfred => alfred}/rest/data_points/__init__.py (100%) rename {src/alfred => alfred}/rest/data_points/base.py (100%) rename {src/alfred => alfred}/rest/data_points/v1.py (81%) rename {src/alfred => alfred}/rest/files/__init__.py (100%) rename {src/alfred => alfred}/rest/files/base.py (100%) rename {src/alfred => alfred}/rest/files/typed.py (100%) rename {src/alfred => alfred}/rest/files/v1.py (92%) rename {src/alfred => alfred}/rest/jobs/__init__.py (100%) rename {src/alfred => alfred}/rest/jobs/base.py (89%) rename {src/alfred => alfred}/rest/jobs/typed.py (100%) rename {src/alfred => alfred}/rest/jobs/v1.py (81%) rename {src/alfred => alfred}/rest/sessions/__init__.py (100%) rename {src/alfred => alfred}/rest/sessions/base.py (100%) rename {src/alfred => alfred}/rest/sessions/v1.py (85%) create mode 100644 alfred/typings/__init__.py rename {src/alfred => alfred}/typings/misc.py (100%) create mode 100644 alfred/utils/__init__.py rename {src/alfred => alfred}/utils/logging.py (98%) delete mode 100644 src/alfred/__init__.py delete mode 100644 src/alfred/typings/__init__.py delete mode 100644 src/alfred/utils/__init__.py diff --git a/Makefile b/Makefile index 8d16433..8eb8279 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ clean: rm -rf build/ rm -rf dist/ - rm -rf src/*.egg-info/ - rm -rf src/alfred/__pycache__/ + rm -rf *.egg-info/ + rm -rf alfred/__pycache__/ build: python -m build diff --git a/README.md b/README.md index 663a0ce..a9cb879 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Check out this simple example to get up and running: ```python from alfred.rest import AlfredClient -from alfred.base.config import Configuration +from alfred.base import Configuration config = Configuration.default() auth_config = {"api_key": "AXXXXXXXXXXXXXXXXXXXXXX"} @@ -180,9 +180,9 @@ The `alfred-python` library provides a way to listen to events emitted by Alfred To get started, you need to create an instance of the `AlfredRealTimeClient` class. ```python -from src.alfred.realtime import AlfredRealTimeClient -from src.alfred.base.config import Configuration -from src.alfred.http.typed import AuthConfiguration +from alfred import AlfredRealTimeClient +from alfred.base import Configuration +from alfred import AuthConfiguration config = Configuration.default() @@ -216,7 +216,7 @@ It's particularly useful when you want to listen to a specific event instead of Here's an example of how to listen to a specific event: ```python -from src.alfred.base.constants import FileEvent, JobEvent +from alfred.base import FileEvent, JobEvent # Listen to the specific File Done event client.on(FileEvent.FILE_DONE_EVENT.value, lambda data: print(data)) diff --git a/alfred/__init__.py b/alfred/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/alfred/__init__.py @@ -0,0 +1 @@ + diff --git a/src/alfred/base/__init__.py b/alfred/base/__init__.py similarity index 100% rename from src/alfred/base/__init__.py rename to alfred/base/__init__.py diff --git a/src/alfred/base/config.py b/alfred/base/config.py similarity index 100% rename from src/alfred/base/config.py rename to alfred/base/config.py diff --git a/src/alfred/base/constants.py b/alfred/base/constants.py similarity index 98% rename from src/alfred/base/constants.py rename to alfred/base/constants.py index 30f4609..2c8324f 100644 --- a/src/alfred/base/constants.py +++ b/alfred/base/constants.py @@ -1,6 +1,6 @@ from enum import Enum -from src.alfred.http.typed import ResponseType +from alfred.http.typed import ResponseType # Response type/header mapping RESPONSE_TYPE_HEADER_MAPPING = { diff --git a/src/alfred/base/exceptions.py b/alfred/base/exceptions.py similarity index 100% rename from src/alfred/base/exceptions.py rename to alfred/base/exceptions.py diff --git a/src/alfred/exceptions/__init__.py b/alfred/exceptions/__init__.py similarity index 100% rename from src/alfred/exceptions/__init__.py rename to alfred/exceptions/__init__.py diff --git a/src/alfred/http/__init__.py b/alfred/http/__init__.py similarity index 100% rename from src/alfred/http/__init__.py rename to alfred/http/__init__.py diff --git a/src/alfred/http/http_client.py b/alfred/http/http_client.py similarity index 100% rename from src/alfred/http/http_client.py rename to alfred/http/http_client.py diff --git a/src/alfred/http/typed.py b/alfred/http/typed.py similarity index 100% rename from src/alfred/http/typed.py rename to alfred/http/typed.py diff --git a/src/alfred/realtime/__init__.py b/alfred/realtime/__init__.py similarity index 91% rename from src/alfred/realtime/__init__.py rename to alfred/realtime/__init__.py index 0894dec..4075ffd 100644 --- a/src/alfred/realtime/__init__.py +++ b/alfred/realtime/__init__.py @@ -5,11 +5,11 @@ import socketio # Project Imports -import src.alfred.exceptions -from src.alfred.base.config import ConfigurationDict -from src.alfred.base.constants import EventType, FileEvent, JobEvent -from src.alfred.http.typed import AuthConfiguration -from src.alfred.utils import logging, setup_logger +import alfred.exceptions +from alfred.base.config import ConfigurationDict +from alfred.base.constants import EventType, FileEvent, JobEvent +from alfred.http.typed import AuthConfiguration +from alfred.utils import logging, setup_logger class AlfredRealTimeClient: @@ -48,7 +48,7 @@ def __init__(self, config: ConfigurationDict, auth_config: AuthConfiguration, ve try: self.socket.connect(f"{self.base_url}?apiKey={auth_config.get('api_key')}") except Exception as err: - raise src.alfred.exceptions.ConnectionError(f"Could not establish connection with server: {err}") + raise alfred.exceptions.ConnectionError(f"Could not establish connection with server: {err}") def __on_connect(self): """ diff --git a/src/alfred/rest/__init__.py b/alfred/rest/__init__.py similarity index 83% rename from src/alfred/rest/__init__.py rename to alfred/rest/__init__.py index da03f12..aeefa1e 100644 --- a/src/alfred/rest/__init__.py +++ b/alfred/rest/__init__.py @@ -2,13 +2,13 @@ from typing import Optional # Project imports -from src.alfred.base.config import ConfigurationDict -from src.alfred.http.http_client import HttpClient -from src.alfred.http.typed import AuthConfiguration, HttpConfiguration -from src.alfred.rest.data_points import DataPointsBase, DataPointsFactory -from src.alfred.rest.sessions import SessionsBase, SessionsFactory -from src.alfred.rest.jobs import JobsBase, JobsFactory -from src.alfred.rest.files import FilesBase, FilesFactory +from alfred.base.config import ConfigurationDict +from alfred.http.http_client import HttpClient +from alfred.http.typed import AuthConfiguration, HttpConfiguration +from alfred.rest.data_points import DataPointsBase, DataPointsFactory +from alfred.rest.sessions import SessionsBase, SessionsFactory +from alfred.rest.jobs import JobsBase, JobsFactory +from alfred.rest.files import FilesBase, FilesFactory class AlfredClient: diff --git a/src/alfred/rest/data_points/__init__.py b/alfred/rest/data_points/__init__.py similarity index 100% rename from src/alfred/rest/data_points/__init__.py rename to alfred/rest/data_points/__init__.py diff --git a/src/alfred/rest/data_points/base.py b/alfred/rest/data_points/base.py similarity index 100% rename from src/alfred/rest/data_points/base.py rename to alfred/rest/data_points/base.py diff --git a/src/alfred/rest/data_points/v1.py b/alfred/rest/data_points/v1.py similarity index 81% rename from src/alfred/rest/data_points/v1.py rename to alfred/rest/data_points/v1.py index 90f0037..94b0cb0 100644 --- a/src/alfred/rest/data_points/v1.py +++ b/alfred/rest/data_points/v1.py @@ -2,8 +2,8 @@ from typing import Text # Project imports -from src.alfred.http.http_client import HttpClient -from src.alfred.rest.data_points.base import DataPointsBase +from alfred.http.http_client import HttpClient +from alfred.rest.data_points.base import DataPointsBase class DataPoints(DataPointsBase): diff --git a/src/alfred/rest/files/__init__.py b/alfred/rest/files/__init__.py similarity index 100% rename from src/alfred/rest/files/__init__.py rename to alfred/rest/files/__init__.py diff --git a/src/alfred/rest/files/base.py b/alfred/rest/files/base.py similarity index 100% rename from src/alfred/rest/files/base.py rename to alfred/rest/files/base.py diff --git a/src/alfred/rest/files/typed.py b/alfred/rest/files/typed.py similarity index 100% rename from src/alfred/rest/files/typed.py rename to alfred/rest/files/typed.py diff --git a/src/alfred/rest/files/v1.py b/alfred/rest/files/v1.py similarity index 92% rename from src/alfred/rest/files/v1.py rename to alfred/rest/files/v1.py index ae14097..7a085dd 100644 --- a/src/alfred/rest/files/v1.py +++ b/alfred/rest/files/v1.py @@ -2,13 +2,12 @@ import os import json from typing import Text -from io import BufferedReader from urllib.parse import unquote # Project imports -from src.alfred.rest.files.typed import * # pylint: disable=W0401, W0614 -from src.alfred.http.http_client import HttpClient -from src.alfred.base.exceptions import AlfredMissingArgument +from alfred.rest.files.typed import * # pylint: disable=W0401, W0614 +from alfred.http.http_client import HttpClient +from alfred.base.exceptions import AlfredMissingArgument from .base import FilesBase from .typed import FileDetailsResponse diff --git a/src/alfred/rest/jobs/__init__.py b/alfred/rest/jobs/__init__.py similarity index 100% rename from src/alfred/rest/jobs/__init__.py rename to alfred/rest/jobs/__init__.py diff --git a/src/alfred/rest/jobs/base.py b/alfred/rest/jobs/base.py similarity index 89% rename from src/alfred/rest/jobs/base.py rename to alfred/rest/jobs/base.py index f889701..95f6b3e 100644 --- a/src/alfred/rest/jobs/base.py +++ b/alfred/rest/jobs/base.py @@ -1,6 +1,6 @@ # Native imports from typing import Text, Any -from src.alfred.rest.jobs.typed import CreateJobDict +from alfred.rest.jobs.typed import CreateJobDict from abc import ABC, abstractmethod diff --git a/src/alfred/rest/jobs/typed.py b/alfred/rest/jobs/typed.py similarity index 100% rename from src/alfred/rest/jobs/typed.py rename to alfred/rest/jobs/typed.py diff --git a/src/alfred/rest/jobs/v1.py b/alfred/rest/jobs/v1.py similarity index 81% rename from src/alfred/rest/jobs/v1.py rename to alfred/rest/jobs/v1.py index 8963b46..bd3f627 100644 --- a/src/alfred/rest/jobs/v1.py +++ b/alfred/rest/jobs/v1.py @@ -2,9 +2,9 @@ from typing import Text # Project imports -from src.alfred.rest.jobs.typed import CreateJobDict -from src.alfred.http.http_client import HttpClient -from src.alfred.rest.jobs.base import JobsBase +from alfred.rest.jobs.typed import CreateJobDict +from alfred.http.http_client import HttpClient +from alfred.rest.jobs.base import JobsBase class Jobs(JobsBase): diff --git a/src/alfred/rest/sessions/__init__.py b/alfred/rest/sessions/__init__.py similarity index 100% rename from src/alfred/rest/sessions/__init__.py rename to alfred/rest/sessions/__init__.py diff --git a/src/alfred/rest/sessions/base.py b/alfred/rest/sessions/base.py similarity index 100% rename from src/alfred/rest/sessions/base.py rename to alfred/rest/sessions/base.py diff --git a/src/alfred/rest/sessions/v1.py b/alfred/rest/sessions/v1.py similarity index 85% rename from src/alfred/rest/sessions/v1.py rename to alfred/rest/sessions/v1.py index 916929a..c8f1dfd 100644 --- a/src/alfred/rest/sessions/v1.py +++ b/alfred/rest/sessions/v1.py @@ -2,8 +2,8 @@ from typing import Text # Project imports -from src.alfred.http.http_client import HttpClient -from src.alfred.rest.sessions.base import SessionsBase +from alfred.http.http_client import HttpClient +from alfred.rest.sessions.base import SessionsBase class Sessions(SessionsBase): diff --git a/alfred/typings/__init__.py b/alfred/typings/__init__.py new file mode 100644 index 0000000..0b79e7f --- /dev/null +++ b/alfred/typings/__init__.py @@ -0,0 +1 @@ +from alfred.typings.misc import * diff --git a/src/alfred/typings/misc.py b/alfred/typings/misc.py similarity index 100% rename from src/alfred/typings/misc.py rename to alfred/typings/misc.py diff --git a/alfred/utils/__init__.py b/alfred/utils/__init__.py new file mode 100644 index 0000000..fe8c6a6 --- /dev/null +++ b/alfred/utils/__init__.py @@ -0,0 +1 @@ +from alfred.utils.logging import * diff --git a/src/alfred/utils/logging.py b/alfred/utils/logging.py similarity index 98% rename from src/alfred/utils/logging.py rename to alfred/utils/logging.py index 0518a5f..d91de9d 100644 --- a/src/alfred/utils/logging.py +++ b/alfred/utils/logging.py @@ -6,7 +6,7 @@ from typing import Union # Project imports -from src.alfred.typings import LoggingOptions +from alfred.typings import LoggingOptions def setup_logger(options: LoggingOptions): diff --git a/pyproject.toml b/pyproject.toml index d15deab..60be32e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,5 +27,4 @@ dependencies = [ homepage = "https://github.com/tagshelfsrl/alfred-python" [tool.setuptools.packages.find] -where = ["src"] include = ["alfred", "alfred.*"] diff --git a/src/alfred/__init__.py b/src/alfred/__init__.py deleted file mode 100644 index f102a9c..0000000 --- a/src/alfred/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.0.1" diff --git a/src/alfred/typings/__init__.py b/src/alfred/typings/__init__.py deleted file mode 100644 index 50a738d..0000000 --- a/src/alfred/typings/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from src.alfred.typings.misc import * diff --git a/src/alfred/utils/__init__.py b/src/alfred/utils/__init__.py deleted file mode 100644 index 11f6ea8..0000000 --- a/src/alfred/utils/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from src.alfred.utils.logging import * From c0fd44cc32581323dad5c635b9a74a304157908d Mon Sep 17 00:00:00 2001 From: "Ronnie A. Baez Sesto" Date: Mon, 20 May 2024 16:46:49 -0400 Subject: [PATCH 4/5] fix: release-please-action org rename and typo (#37) --- .github/workflows/on-merge.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/on-merge.yml b/.github/workflows/on-merge.yml index 161131e..22ca210 100644 --- a/.github/workflows/on-merge.yml +++ b/.github/workflows/on-merge.yml @@ -39,12 +39,11 @@ jobs: environment: ${{ steps.target.outputs.environment }} pypi_url: ${{ steps.target.outputs.url }} steps: - # - uses: googleapis/release-please-action@v4 - - uses: google-github-actions/release-please-action@v4 + - uses: googleapis/release-please-action@v4 id: release with: release-type: python - token: ${{ secrets.PAT_TOKEN }} + token: ${{ secrets.PPAT_TOKEN }} target-branch: ${{ github.ref_name }} - name: determine target environment id: target From dc9ea9951a79e224d240ac06ed3f7b4a572ef7f9 Mon Sep 17 00:00:00 2001 From: TagShelf <32621192+tagshelf@users.noreply.github.com> Date: Mon, 20 May 2024 17:06:33 -0400 Subject: [PATCH 5/5] chore(master): release 0.5.0 (#38) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 13 +++++++++++++ pyproject.toml | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8efb275..6bbfeb6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.4.0"} +{".":"0.5.0"} diff --git a/CHANGELOG.md b/CHANGELOG.md index b654edc..fd191bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [0.5.0](https://github.com/tagshelfsrl/alfred-python/compare/v0.4.0...v0.5.0) (2024-05-20) + + +### Features + +* implement realtime functionality. ([#18](https://github.com/tagshelfsrl/alfred-python/issues/18)) ([1b0d070](https://github.com/tagshelfsrl/alfred-python/commit/1b0d070932db0d46bef20546a78bdb70a4ccebf4)) + + +### Bug Fixes + +* move the alfred package up in the hierarchy out of the src/ folder. ([#36](https://github.com/tagshelfsrl/alfred-python/issues/36)) ([fa5a845](https://github.com/tagshelfsrl/alfred-python/commit/fa5a8452b573ea09c1ea66438b84082f257a727f)) +* release-please-action org rename and typo ([#37](https://github.com/tagshelfsrl/alfred-python/issues/37)) ([c0fd44c](https://github.com/tagshelfsrl/alfred-python/commit/c0fd44cc32581323dad5c635b9a74a304157908d)) + ## [0.4.0](https://github.com/tagshelfsrl/alfred-python/compare/v0.3.0...v0.4.0) (2024-05-14) diff --git a/pyproject.toml b/pyproject.toml index 60be32e..8c139e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "alfred-python" -version = "0.4.0" +version = "0.5.0" authors = [{ name = "Tagshelf LLC", email = "support@tagshelf.com" }] description = "Python library designed to simplify and streamline interactions with the Alfred API" readme = "README.md"