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

Compare 2 #40

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
signature.png
**/log.txt
log.txt
97 changes: 58 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ A simple Python wrapper for Oracle OFS REST API

## Models

Starting with OFS 1.17 we are adding models for the most common entities. All models should be imported from `ofsc.models`. All existing create functions will be transitioned to models. In OFS 2.0 all functions will use models
Starting with OFS 1.17 we added models for the most common entities and metadata. All models should be imported from `ofsc.models`. All existing create functions will be transitioned to models. In OFS 2.0 all functions will use models

The models are based on the Pydantic BaseModel, so it is possible to build an entity using the `parse_obj` or `parse_file` static methods.
The models are based on the Pydantic BaseModel, so it is possible to build an entity using the `model_validate` static methods.

Currently implemented:
- ActivityTypeGroup
- ActivityType
- Property
- Workskill
- WorkSkillCondition
- Workzone
- Property


Experimental:
- Resource
Expand All @@ -35,53 +38,60 @@ Experimental:


### Core / Events
get_subscriptions(self, response_type=TEXT_RESPONSE)
create_subscription(self, data, response_type=TEXT_RESPONSE)
delete_subscription(self, subscription_id, response_type=FULL_RESPONSE)
get_subscription_details(self, subscription_id, response_type=TEXT_RESPONSE)
get_events(self, params, response_type=TEXT_RESPONSE)
get_subscriptions(self, response_type=JSON_RESPONSE)
create_subscription(self, data, response_type=JSON_RESPONSE)
delete_subscription(self, subscription_id, response_type=JSON_RESPONSE)
get_subscription_details(self, subscription_id, response_type=JSON_RESPONSE)
get_events(self, params, response_type=JSON_RESPONSE)

### Core / Resources
create_resource(self, resourceId, data, response_type=TEXT_RESPONSE)
get_resource(self, resource_id, inventories=False, workSkills=False, workZones=False, workSchedules=False , response_type=TEXT_RESPONSE)
get_position_history(self, resource_id,date,response_type=TEXT_RESPONSE)
get_resource_route(self, resource_id, date, activityFields = None, offset=0, limit=100, response_type=TEXT_RESPONSE)
get_resource_descendants(self, resource_id, resourceFields=None, offset=0, limit=100, inventories=False, workSkills=False, workZones=False, workSchedules=False, response_type=TEXT_RESPONSE)
create_resource(self, resourceId, data, response_type=JSON_RESPONSE)
get_resource(self, resource_id, inventories=False, workSkills=False, workZones=False, workSchedules=False , response_type=JSON_RESPONSE)
get_position_history(self, resource_id,date,response_type=JSON_RESPONSE)
get_resource_route(self, resource_id, date, activityFields = None, offset=0, limit=100, response_type=JSON_RESPONSE)
get_resource_descendants(self, resource_id, resourceFields=None, offset=0, limit=100, inventories=False, workSkills=False, workZones=False, workSchedules=False, response_type=JSON_RESPONSE)

### Core / Users
get_users(self, offset=0, limit=100, response_type=FULL_RESPONSE)
get_user(self, login, response_type=FULL_RESPONSE):
update_user (self, login, data, response_type=TEXT_RESPONSE)
create_user(self, login, data, response_type=FULL_RESPONSE)
delete_user(self, login, response_type=FULL_RESPONSE)
get_users(self, offset=0, limit=100, response_type=JSON_RESPONSE)
get_user(self, login, response_type=JSON_RESPONSE):
update_user (self, login, data, response_type=JSON_RESPONSE)
create_user(self, login, data, response_type=JSON_RESPONSE)
delete_user(self, login, response_type=JSON_RESPONSE)

### Core / Daily Extract
get_daily_extract_dates(self, response_type=FULL_RESPONSE)
get_daily_extract_files(self, date, response_type=FULL_RESPONSE)
get_daily_extract_file(self, date, filename, response_type=FULL_RESPONSE)
get_daily_extract_dates(self, response_type=JSON_RESPONSE)
get_daily_extract_files(self, date, response_type=JSON_RESPONSE)
get_daily_extract_file(self, date, filename, response_type=JSON_RESPONSE)
\
### Metadata / Activity Type Groups
get_activity_type_groups (self, expand="parent", offset=0, limit=100, response_type=JSON_RESPONSE)
get_activity_type_group (self,label, response_type=JSON_RESPONSE)

### Metadata / Activity Types
get_activity_types(self, offset=0, limit=100, response_type=JSON_RESPONSE)
get_activity_type (self, label, response_type=JSON_RESPONSE)

### Metadata / Capacity
get_capacity_areas (self, expand="parent", fields=capacityAreasFields, status="active", queryType="area", response_type=FULL_RESPONSE)
get_capacity_area (self,label, response_type=FULL_RESPONSE)
get_capacity_areas (self, expand="parent", fields=capacityAreasFields, status="active", queryType="area", response_type=JSON_RESPONSE)
get_capacity_area (self,label, response_type=JSON_RESPONSE)

### Metadata / Activity Types
get_activity_type_groups (self, expand="parent", offset=0, limit=100, response_type=FULL_RESPONSE)
get_activity_type_group (self,label, response_type=FULL_RESPONSE)
get_activity_types(self, offset=0, limit=100, response_type=FULL_RESPONSE)
get_activity_type (self, label, response_type=FULL_RESPONSE)
### Metadata / Inventory
get_inventory_types (self, offset=0, limit=100, response_type=JSON_RESPONSE)
get_inventory_type (self, label, response_type=JSON_RESPONSE)
create_or_replace_inventory_type(self, inventory: InventoryType, response_type=JSON_RESPONSE)

### Metadata / Properties
get_properties (self, offset=0, limit=100, response_type=FULL_RESPONSE)
get_properties (self, offset=0, limit=100, response_type=JSON_RESPONSE)
get_property(self, label: str, response_type=JSON_RESPONSE)
create_or_replace_property(self, property: Property, response_type=JSON_RESPONSE)

### Metadata / Workskills
get_workskills (self, offset=0, limit=100, response_type=FULL_RESPONSE)
get_workskill(self, label: str, response_type=FULL_RESPONSE)
create_or_update_workskill(self, skill: Workskill, response_type=FULL_RESPONSE)
delete_workskill(self, label: str, response_type=FULL_RESPONSE)
get_workskill_conditions(self, response_type=FULL_RESPONSE)
replace_workskill_conditions(self, data: WorskillConditionList, response_type=FULL_RESPONSE
get_workskills (self, offset=0, limit=100, response_type=JSON_RESPONSE)
get_workskill(self, label: str, response_type=JSON_RESPONSE)
create_or_update_workskill(self, skill: Workskill, response_type=JSON_RESPONSE)
delete_workskill(self, label: str, response_type=JSON_RESPONSE)
get_workskill_conditions(self, response_type=JSON_RESPONSE)
replace_workskill_conditions(self, data: WorskillConditionList, response_type=JSON_RESPONSE)

### Metadata / Plugins
import_plugin(self, plugin: str)
Expand All @@ -90,8 +100,8 @@ Experimental:
### Metadata / Resource Types
get_resource_types(self, response_type=JSON_RESPONSE):

### Metadata / workzones
get_workzones(self, response_type=FULL_RESPONSE)
### Metadata / Workzones
get_workzones(self, response_type=JSON_RESPONSE)

## Test History

Expand All @@ -102,10 +112,11 @@ OFS REST API Version | PyOFSC
21D| 1.15
22B| 1.16, 1.17
22D| 1.18
24A| 2.0

## Deprecation Warning

Starting in OFSC 2.0 (estimated for December 2022) all functions will have to be called using the API name (Core or Metadata). See the examples.
Starting in OFSC 2.0 all functions are called using the API name (Core or Metadata). See the examples.

Instead of

Expand All @@ -117,4 +128,12 @@ It will be required to use the right API module:
instance = OFSC(..)
list_of_activites = instance.core.get_activities(...)

During the transition period a DeprecationWarning will be raised if the functions are used in the old way
During the transition period a DeprecationWarning will be raised if the functions are used in the old way

## What's new in OFSC 2.0

- All metadata functions now use models, when available
- All functions are now using the API name (Core or Metadata)
- All functions return a python object by default. If there is an available model it will be used, otherwise a dict will be returned (see `response_type` parameter and `auto_model` parameter)
- Errors during API calls can raise exceptions and will by default when returning an object (see `auto_raise` parameter)
- JSON_RESPONSE and TEXT_RESPONSE are now deprecated. Use `response_type` parameter to control the response type
4 changes: 2 additions & 2 deletions examples/get_capacity_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import logging
import pprint

from config import Config
from flatten_dict import flatten
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC

from config import Config
from ofsc import FULL_RESPONSE, OBJ_RESPONSE, OFSC

capacityAreasFields = "label,name,type,status,parent.name,parent.label"

Expand Down
10 changes: 5 additions & 5 deletions examples/get_users_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import argparse
import logging

import ofsc
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC

from config import Config

import ofsc
from ofsc import FULL_RESPONSE, OBJ_RESPONSE, OFSC


def init_script():
# Parse arguments
Expand Down Expand Up @@ -38,7 +38,7 @@ def init_script():


def get_users(instance):
response = instance.core.get_users(offset=0, limit=100, response_type=JSON_RESPONSE)
response = instance.core.get_users(offset=0, limit=100, response_type=OBJ_RESPONSE)
total_results = response["totalResults"]
offset = response["offset"]
final_items_list = response["items"]
Expand All @@ -50,7 +50,7 @@ def get_users(instance):
)
offset = offset + 100
response_json = instance.core.get_users(
offset=offset, response_type=JSON_RESPONSE
offset=offset, response_type=OBJ_RESPONSE
)
total_results = response_json["totalResults"]
items = response_json["items"]
Expand Down
10 changes: 5 additions & 5 deletions examples/get_work_skill_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from logging import basicConfig, debug, info, warning
from typing import AnyStr, List

import ofsc
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC
from ofsc.models import WorkskillCondition, WorskillConditionList
from config import Config
from openpyxl import Workbook

from config import Config
import ofsc
from ofsc import FULL_RESPONSE, OBJ_RESPONSE, OFSC
from ofsc.models import WorkskillCondition, WorskillConditionList


def init_script():
Expand Down Expand Up @@ -44,7 +44,7 @@ def init_script():


def get_workskill_list():
response = instance.metadata.get_workskill_conditions(response_type=JSON_RESPONSE)
response = instance.metadata.get_workskill_conditions(response_type=OBJ_RESPONSE)
ws_list = WorskillConditionList.parse_obj(response["items"])
return ws_list

Expand Down
10 changes: 5 additions & 5 deletions examples/get_workzones.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from logging import basicConfig, debug, info, warning
from typing import AnyStr, List

import ofsc
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC
from ofsc.models import Workzone, WorkzoneList
from config import Config
from openpyxl import Workbook

from config import Config
import ofsc
from ofsc import FULL_RESPONSE, OBJ_RESPONSE, OFSC
from ofsc.models import Workzone, WorkzoneList


def init_script():
Expand Down Expand Up @@ -45,7 +45,7 @@ def init_script():


def get_workzone_list():
response = instance.metadata.get_workzones(response_type=JSON_RESPONSE)
response = instance.metadata.get_workzones(response_type=OBJ_RESPONSE)
return WorkzoneList.parse_obj(response["items"])


Expand Down
45 changes: 29 additions & 16 deletions ofsc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
import base64
import logging
from functools import wraps
from http import client
from urllib import response
from warnings import warn

from .common import FULL_RESPONSE, JSON_RESPONSE, TEXT_RESPONSE, wrap_return
from .common import FULL_RESPONSE, OBJ_RESPONSE, TEXT_RESPONSE
from .core import OFSCore
from .metadata import OFSMetadata
from .models import OFSConfig
from .oauth import OFSOauth2


class OFSC:
# 202308 The API portal was deprecated, so the default URL becomes {companyname}.fs.ocs.oraclecloud.com

# the default URL becomes {companyname}.fs.ocs.oraclecloud.com
def __init__(
self, clientID, companyName, secret, root=None, baseUrl=None, useToken=False
self,
clientID,
companyName,
secret,
root=None,
baseUrl=None,
useToken=False,
enable_auto_raise=True,
enable_auto_model=True,
):

self._config = OFSConfig(
baseURL=baseUrl,
clientID=clientID,
secret=secret,
companyName=companyName,
root=root,
useToken=useToken,
auto_raise=enable_auto_raise, # 20240401: This is a new feature that will raise an exception if the API returns an error
auto_model=enable_auto_model, # 20240401: This is a new feature that will return a pydantic model if the API returns a 200
)
self._core = OFSCore(config=self._config)
self._metadata = OFSMetadata(config=self._config)
Expand Down Expand Up @@ -62,6 +68,17 @@ def oauth2(self) -> OFSOauth2:
self._oauth = OFSOauth2(config=self._config)
return self._oauth

@property
def auto_model(self):
return self._config.auto_model

@auto_model.setter
def auto_model(self, value):
self._config.auto_model = value
self._core.config.auto_model = value
self._metadata.config.auto_model = value
self._oauth.config.auto_model = value

def __str__(self) -> str:
return f"baseURL={self._config.baseURL}"

Expand All @@ -75,18 +92,14 @@ def __getattr__(self, method_name):

def wrapper(*args, **kwargs):
if method_name in self._core_methods:
warn(
f"{method_name} was called without the API name (Core). This will be deprecated in OFSC 2.0",
DeprecationWarning,
raise NotImplementedError(
f"{method_name} was called without the API name (Core). This was deprecated in OFSC 2.0"
)
return getattr(self.core, method_name)(*args, **kwargs)

if method_name in self._metadata_methods:
warn(
f"{method_name} was called without the API name (Metadata). This will be deprecated in OFSC 2.0",
DeprecationWarning,
raise NotImplementedError(
f"{method_name} was called without the API name (Metadata). This was deprecated in OFSC 2.0"
)
return getattr(self.metadata, method_name)(*args, **kwargs)
raise Exception("method not found")

return wrapper
Loading