Skip to content

Commit d38ab32

Browse files
btoronbe-ant
andauthored
Code revamping (#20)
* Added get_workzones * completed tests * Fixed Workskill and added model * Fixed error in definition Co-authored-by: Boris Anthony <boris@st3am.us>
1 parent 5e3c6de commit d38ab32

13 files changed

Lines changed: 307 additions & 19 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ dist/
33
.env
44
*.pyc
55
.DS_Store
6+
*.xslx

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,18 @@ Currently implemented
6262

6363
### Metadata / properties
6464
get_properties (self, offset=0, limit=100, response_type=FULL_RESPONSE)
65-
get_all_properties(self, initial_offset=0, limit=100)
65+
get_all_properties(self, initial_offset=0, limit=100)
6666

6767
### Metadata / workskills
6868
get_workskills (self, offset=0, limit=100, response_type=FULL_RESPONSE)
6969
get_workskill(self, label: str, response_type=FULL_RESPONSE)
7070
create_or_update_workskill(self, skill: Workskill, response_type=FULL_RESPONSE)
7171
delete_workskill(self, label: str, response_type=FULL_RESPONSE)
72+
get_workskill_conditions(self, response_type=FULL_RESPONSE):
73+
replace_workskill_conditions(self, data: WorskillConditionList, response_type=FULL_RESPONSE
7274

75+
### Metadata / workzones
76+
get_workzones(self, response_type=FULL_RESPONSE)
7377
## Test History
7478

7579
OFS REST API Version | PyOFSC

examples/get_work_skill_conditions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import ofsc
88
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC
9-
from ofsc.models import WorkskillCondition
9+
from ofsc.models import WorkskillCondition, WorskillConditionList
1010
from openpyxl import Workbook
1111

1212
from config import Config
@@ -45,11 +45,11 @@ def init_script():
4545

4646
def get_workskill_list():
4747
response = instance.metadata.get_workskill_conditions(response_type=JSON_RESPONSE)
48-
ws_list = [WorkskillCondition.parse_obj(item) for item in response["items"]]
48+
ws_list = WorskillConditionList.parse_obj(response["items"])
4949
return ws_list
5050

5151

52-
def write_xls(filename: str, wsc_list: List[WorkskillCondition]):
52+
def write_xls(filename: str, wsc_list: WorskillConditionList):
5353
def convert(data):
5454
match data:
5555
case None:

examples/get_workzones.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!python
2+
import argparse
3+
import logging
4+
import pprint
5+
from logging import basicConfig, debug, info, warning
6+
from typing import AnyStr, List
7+
8+
import ofsc
9+
from ofsc import FULL_RESPONSE, JSON_RESPONSE, OFSC
10+
from ofsc.models import Workzone, WorkzoneList
11+
from openpyxl import Workbook
12+
13+
from config import Config
14+
15+
16+
def init_script():
17+
global args, instance, pp
18+
pp = pprint.PrettyPrinter(indent=4)
19+
parser = argparse.ArgumentParser(description="Extract users from OFSC instance")
20+
parser.add_argument(
21+
"--verbose",
22+
type=int,
23+
choices={0, 1, 2, 3},
24+
default=1,
25+
help="Additional messages. 0 is None, 3 is detailed debug",
26+
)
27+
parser.add_argument(
28+
"--output",
29+
type=str,
30+
default="output.xlsx",
31+
help="Excel sheet to update",
32+
)
33+
args = parser.parse_args()
34+
35+
# create logger
36+
basicConfig(level=40 - 10 * int(args.verbose))
37+
instance = OFSC(
38+
clientID=Config.OFSC_CLIENT_ID,
39+
secret=Config.OFSC_CLIENT_SECRET,
40+
companyName=Config.OFSC_COMPANY,
41+
baseUrl=Config.OFSC_BASE_URL,
42+
)
43+
info(f"Creating connection for {Config.OFSC_COMPANY} {Config.OFSC_CLIENT_ID}")
44+
return instance
45+
46+
47+
def get_workzone_list():
48+
response = instance.metadata.get_workzones(response_type=JSON_RESPONSE)
49+
return WorkzoneList.parse_obj(response["items"])
50+
51+
52+
def write_xls(filename: str, wz_list: WorkzoneList):
53+
def convert(data):
54+
match data:
55+
case None:
56+
return data
57+
case str():
58+
return data
59+
case bool():
60+
return data
61+
case int():
62+
return data
63+
case _:
64+
return str(data)
65+
66+
wb = Workbook()
67+
ws_workzones = wb.active
68+
ws_workzones.title = "Workzones"
69+
workzone_field_names = None
70+
for zone in wz_list:
71+
logging.warning(f"ZONE: {zone} {type(zone)}")
72+
if workzone_field_names is None:
73+
workzone_field_names = list(zone.dict().keys())
74+
print(f"Zone: Workzone Fields: {workzone_field_names}")
75+
ws_workzones.append(workzone_field_names)
76+
data = [convert(value) for value in zone.dict().values()]
77+
ws_workzones.append(data)
78+
wb.save(filename)
79+
return None
80+
81+
82+
init_script()
83+
wsc_list = get_workzone_list()
84+
write_xls(args.output, wsc_list)

ofsc/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import base64
22
import logging
3+
from functools import wraps
34
from http import client
45
from urllib import response
56
from warnings import warn
67

7-
from .common import FULL_RESPONSE, JSON_RESPONSE, TEXT_RESPONSE
8+
from .common import FULL_RESPONSE, JSON_RESPONSE, TEXT_RESPONSE, wrap_return
89
from .core import OFSCore
910
from .metadata import OFSMetadata
1011
from .models import OFSConfig

ofsc/common.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1-
TEXT_RESPONSE=1
2-
FULL_RESPONSE=2
3-
JSON_RESPONSE=3
1+
import logging
2+
from functools import wraps
3+
4+
TEXT_RESPONSE = 1
5+
FULL_RESPONSE = 2
6+
JSON_RESPONSE = 3
7+
8+
9+
def wrap_return(*a, **kw):
10+
"""
11+
Decorator @return_as wraps the function
12+
and decides the return type and if we launch an exception
13+
"""
14+
15+
def decorator(func):
16+
@wraps(func)
17+
def wrapper(*args, **kwargs):
18+
# Pre:
19+
response_type = kwargs.get(
20+
"response_type", kw.get("response_type", FULL_RESPONSE)
21+
)
22+
kwargs.pop("response_type", None)
23+
response = func(*args, **kwargs)
24+
# post:
25+
logging.warning(response)
26+
if response_type == FULL_RESPONSE:
27+
return response
28+
elif response_type == JSON_RESPONSE:
29+
return response.json()
30+
else:
31+
return response.text
32+
return result
33+
34+
return wrapper
35+
36+
return decorator

ofsc/metadata.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import requests
99

10-
from .common import FULL_RESPONSE, JSON_RESPONSE, TEXT_RESPONSE
10+
from .common import FULL_RESPONSE, JSON_RESPONSE, TEXT_RESPONSE, wrap_return
1111
from .models import (
1212
OFSApi,
1313
OFSConfig,
@@ -199,7 +199,7 @@ def get_workskill_conditions(self, response_type=FULL_RESPONSE):
199199
return response.text
200200

201201
def replace_workskill_conditions(
202-
self, data=WorskillConditionList, response_type=FULL_RESPONSE
202+
self, data: WorskillConditionList, response_type=FULL_RESPONSE
203203
):
204204
url = urljoin(self.baseUrl, f"/rest/ofscMetadata/v1/workSkillConditions")
205205
content = '{"items":' + data.json(exclude_none=True) + "}"
@@ -212,3 +212,19 @@ def replace_workskill_conditions(
212212
return response.json()
213213
else:
214214
return response.text
215+
216+
# 202208 Workzones
217+
@wrap_return(response_type=JSON_RESPONSE, expected=[200])
218+
def get_workzones(
219+
self,
220+
offset=0,
221+
limit=100,
222+
):
223+
url = urljoin(self.baseUrl, "/rest/ofscMetadata/v1/workZones")
224+
params = {"offset": offset, "limit": limit}
225+
response = requests.get(
226+
url,
227+
headers=self.headers,
228+
params=params,
229+
)
230+
return response

ofsc/models.py

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import typing
33
from enum import Enum
44
from functools import lru_cache
5-
from typing import Any, List
5+
from typing import Any, List, Optional
66

77
from pydantic import BaseModel, validator
88

@@ -45,28 +45,53 @@ class SharingEnum(str, Enum):
4545

4646

4747
class TranslationEnum(str, Enum):
48-
en: "en"
49-
es: "es"
50-
pt: "pt"
48+
en = "en"
49+
es = "es"
50+
pt = "pt"
51+
fr = "fr"
52+
br = "br"
53+
el = "el"
5154

5255

56+
# Work skills
5357
class Translation(BaseModel):
5458
language: TranslationEnum = "en"
5559
name: str
60+
languageISO: Optional[str]
61+
62+
63+
class TranslationList(BaseModel):
64+
__root__: List[Translation]
65+
66+
def __iter__(self):
67+
return iter(self.__root__)
68+
69+
def __getitem__(self, item):
70+
return self.__root__[item]
5671

5772

5873
class Workskill(BaseModel):
5974
label: str
6075
active: bool = True
6176
name: str = ""
6277
sharing: SharingEnum
63-
translations: List[Translation] = []
78+
translations: TranslationList = []
6479

6580
@validator("translations", always=True)
6681
def set_default(cls, field_value, values):
6782
return field_value or [Translation(name=values["name"])]
6883

6984

85+
class WorkskillList(BaseModel):
86+
__root__: List[Workskill]
87+
88+
def __iter__(self):
89+
return iter(self.__root__)
90+
91+
def __getitem__(self, item):
92+
return self.__root__[item]
93+
94+
7095
class Condition(BaseModel):
7196
label: str
7297
function: str
@@ -85,3 +110,28 @@ class WorkskillCondition(BaseModel):
85110

86111
class WorskillConditionList(BaseModel):
87112
__root__: List[WorkskillCondition]
113+
114+
def __iter__(self):
115+
return iter(self.__root__)
116+
117+
def __getitem__(self, item):
118+
return self.__root__[item]
119+
120+
121+
# Workzones
122+
class Workzone(BaseModel):
123+
workZoneLabel: str
124+
workZoneName: str
125+
status: str
126+
travelArea: str
127+
keys: List[Any]
128+
129+
130+
class WorkzoneList(BaseModel):
131+
__root__: List[Workzone]
132+
133+
def __iter__(self):
134+
return iter(self.__root__)
135+
136+
def __getitem__(self, item):
137+
return self.__root__[item]

poetry.lock

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "ofsc"
3-
version = "1.17.2"
3+
version = "1.17.4.4"
44
license = "MIT"
55
description = "Python wrapper for Oracle Field Service API"
66
authors = ["Borja Toron <borja.toron@gmail.com>"]
@@ -16,6 +16,7 @@ pydantic = "^1.9.1"
1616

1717
[tool.poetry.dev-dependencies]
1818
openpyxl = "^3.0.10"
19+
pyarmor = "^7.6.0"
1920

2021
[build-system]
2122
requires = ["poetry-core>=1.0.0"]

0 commit comments

Comments
 (0)