Skip to content

Commit c697448

Browse files
Static attributes (#14)
* experimenting with adding of static attributes * not really working that well atm, pycharm ignores that subobjects returns lists * update for latest python versions
1 parent 7adaea9 commit c697448

File tree

13 files changed

+202
-42
lines changed

13 files changed

+202
-42
lines changed

.todo.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,38 @@
88
# ** d2fprgvn_GetValueName(d2fctx, D2FP_ALT_STY, D2FC_ALST_CAUTION, &vname)
99
# ** returns "Caution" in the vname [OUT] parameter.
1010

11+
1112
# todo:
1213
# ** d2fprgvv_GetValueValue(d2fctx, D2FP_ALT_STY, "Caution", &val)
1314
# ** returns 1 in the val [OUT] parameter.
1415

16+
1517
# todo:
1618
# d2fobdu_Duplicate( d2fctx *pd2fctx, d2fob *new_owner, d2fob *pd2fob_src, d2fob **ppd2fob_dst, text *new_name );
1719

20+
1821
# todo:
1922
# d2fobfo_FindObj(d2fctx *pd2fctx, d2fob *owner, text *name, d2fotyp objtyp, d2fob **ppd2fob );
23+
24+
25+
# todo: property numbers for data sources and arguments..
26+
# 368 -- Query Data Source Columns
27+
# 369 -- Query Data Source Arguments
28+
# 420 -- Insert Procedure Result Set Columns
29+
# 421 -- Insert Procedure Arguments
30+
# 423 -- Update Procedure Result Set Columns
31+
# 424 -- Update Procedure Arguments
32+
# 426 -- Delete Procedure Result Set Columns
33+
# 427 -- Delete Procedure Arguments
34+
# 429 -- Lock Procedure Result Set Columns
35+
# 430 -- Lock Procedure Arguments
36+
# 508 -- Query Column Object
37+
# 509 -- Query Argument Object
38+
# 510 -- Insert Column Object
39+
# 511 -- Insert Argument Object
40+
# 512 -- Update Column Object
41+
# 513 -- Update Argument Object
42+
# 514 -- Delete Column Object
43+
# 515 -- Delete Argument Object
44+
# 516 -- Lock Column Object
45+
# 517 -- Lock Argument Object

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
language: python
22
python:
3-
- '3.7'
4-
- '3.8'
3+
- '3.9'
4+
- '3.10'
55
install:
66
- pip install -r requirements.txt
77
- pip install .

media/coverage.svg

Lines changed: 2 additions & 2 deletions
Loading

pyoracle_forms/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ def initialize_context(version: str = "12c", encoding: str = "utf-8") -> None:
4646
api_objects = read_api_objects(version=version)
4747

4848
for forms_object in registered_objects.values():
49-
add_properties(forms_object, api_objects)
49+
if forms_object != Module:
50+
add_properties(forms_object, api_objects)

pyoracle_forms/context.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ def property_type(property_number: int) -> int:
218218
return int(api_function("d2fprgt_GetType", (c_uint,))(property_number))
219219

220220

221+
def property_constant_number(property_const_name: str) -> int:
222+
return handled_api_function("d2fprgcv_GetConstValue", (c_char_p, c_void_p), 1)(
223+
property_const_name.encode("utf-8"), c_int()
224+
).value
225+
226+
221227
def object_number(obj_name: str) -> int:
222228
return int(
223229
handled_api_function(

pyoracle_forms/error_handling.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from functools import wraps
21
from typing import NoReturn
32

43
error_mapping = {

pyoracle_forms/forms_api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import json
22
import pathlib
3-
from typing import Dict, Tuple, Optional
43
from ctypes import *
54
from os import pathsep, environ
65
from os.path import exists, abspath, join
7-
6+
from typing import Dict, Tuple, Optional
87

98
dll_names = {
109
"12c": ("frmd2f.dll", "msvcr100"),

pyoracle_forms/forms_objects.py

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,78 @@
11
from __future__ import annotations
22

33
from ctypes import c_void_p
4-
from typing import Optional, Any, Type
54
from types import TracebackType
5+
from typing import Optional, Type, List
66

77
from .context import create_module
88
from .context import load_module
99
from .context import save_module
1010
from .generic_object import GenericObject, BaseObject, FormsObjects
11-
from .misc import forms_object
11+
from .misc import forms_object, Text, Number, Object, Bool, Subobjects
1212

1313

1414
@forms_object
1515
class Module(BaseObject):
1616
object_type = FormsObjects.module
1717

18+
name = Text("NAME")
19+
comments = Text("COMMENT")
20+
console_window = Text("CONSOLE_WIN")
21+
cursor_mode = Number("CRSR_MODE")
22+
direction = Number("LANG_DIR")
23+
first_navigation_data_block = Text("FRST_NAVIGATION_BLK_NAM")
24+
menu_module = Text("MNU_MOD")
25+
menu_role = Text("MNU_ROLE")
26+
initial_menu = Text("INIT_MNU")
27+
form_horizontal_toolbar_canvas = Text("HORZ_TLBR_CNV")
28+
form_vertical_toolbar_canvas = Text("VERT_TLBR_CNV")
29+
mouse_navigation_limit = Number("MOUSE_NAVIGATION_LMT")
30+
current_record_visual_attribute_group = Text("REC_VAT_GRP_NAM")
31+
savepoint_mode = Bool("SVPNT_MODE")
32+
title = Text("TITLE")
33+
use_3d_controls = Bool("USE_3D_CNTRLS")
34+
validation_unit = Number("VALIDATION_UNIT")
35+
title_string_id = Number("TITLE_STRID")
36+
interaction_mode = Number("INTERACTION_MODE")
37+
maximum_query_time = Number("MAX_QRY_TIME")
38+
maximum_records_fetched = Number("MAX_RECS_FETCHED")
39+
isolation_mode = Number("ISOLATION_MODE")
40+
parent_objects_module = Text("PAR_MODULE")
41+
parent_objects_module_type = Number("PAR_MODTYP")
42+
parent_object_name = Text("PAR_NAM")
43+
parent_objects_file_name = Text("PAR_FLNAM")
44+
parent_objects_file_path = Text("PAR_FLPATH")
45+
runtime_compatibility_mode = Number("RUNTIME_COMP")
46+
parent_objects_type = Number("PAR_TYP")
47+
help_book_title = Text("HELP_BOOK_TITLE")
48+
defer_required_enforcement = Number("NEWDEFER_REQ_ENF")
49+
50+
alerts = Subobjects["Alert"]("ALERT") # type: List[Alert]
51+
attached_libraries: List[AttachedLibrary] = Subobjects("ATT_LIB")
52+
data_blocks: List[DataBlock] = Subobjects("BLOCK")
53+
canvases: List[Canvas] = Subobjects("CANVAS")
54+
editors: List[Editor] = Subobjects("EDITOR")
55+
form_parameters: List[FormParameter] = Subobjects("FORM_PARAM")
56+
lovs: List[LOV] = Subobjects("LOV")
57+
menus: List[Menu] = Subobjects("MENU")
58+
triggers: List[Trigger] = Subobjects("TRIGGER")
59+
visual_attributes: List[VisualAttribute] = Subobjects("VIS_ATTR")
60+
windows: List[Window] = Subobjects("WINDOW")
61+
reports: List[Report] = Subobjects("REPORT")
62+
object_groups: List[ObjectGroup] = Subobjects("OBJ_GRP")
63+
program_units: List[ProgramUnit] = Subobjects("PROG_UNIT")
64+
property_classes: List[PropertyClass] = Subobjects("PROP_CLASS")
65+
record_groups: List[RecordGroup] = Subobjects("REC_GRP")
66+
events: List[Event] = Subobjects("EVENT")
67+
68+
first_data_block_object = Object("FRST_NAVIGATION_BLK_OBJ")
69+
70+
next_object = Object("NEXT")
71+
previous_object = Object("PREVIOUS")
72+
source_object = Object("SOURCE")
73+
74+
current_record_va_pointer = Object("REC_VAT_GRP_OBJ")
75+
1876
def __init__(self, module: c_void_p, path: str):
1977
super().__init__(module)
2078
self.path = path
@@ -42,6 +100,10 @@ def save(self, path: Optional[str] = None) -> None:
42100
save_module(module=self, path=path or self.path)
43101

44102

103+
# modu = Module(1, "")
104+
# reveal_type(modu.alerts[0])
105+
106+
45107
@forms_object
46108
class AttachedLibrary(GenericObject):
47109
object_type = FormsObjects.attached_library

pyoracle_forms/generic_object.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import annotations
22

3-
from typing import Callable, Dict, Optional, Any, Tuple, Union, TYPE_CHECKING
4-
from ctypes import c_void_p
53
import enum
4+
from ctypes import c_void_p
5+
from typing import Callable, Dict, Optional, Tuple, Union, TYPE_CHECKING
66

7+
from .context import context
78
from .context import create
89
from .context import destroy
910
from .context import get_boolean
@@ -16,7 +17,6 @@
1617
from .context import set_number
1718
from .context import set_object
1819
from .context import set_text
19-
from .context import context
2020

2121
if TYPE_CHECKING:
2222
from .context import Setter
@@ -88,8 +88,11 @@ class BaseObject:
8888
_object_number: Optional[int]
8989
_as_parameter_: c_void_p
9090

91-
def __init__(self, generic_object: c_void_p) -> None:
92-
self._as_parameter_ = generic_object
91+
def __init__(self, generic_object: Union[c_void_p, BaseObject]) -> None:
92+
try:
93+
self._as_parameter_ = generic_object._as_parameter_
94+
except AttributeError:
95+
self._as_parameter_ = generic_object
9396

9497
def has_property(self, property_number: int) -> bool:
9598
return has_property(self, property_number)

pyoracle_forms/misc.py

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
import enum
22
from ctypes import c_void_p
3-
from typing import Dict, Callable, Type, Tuple, Union, NoReturn, Any, Iterable, List
4-
3+
from typing import (
4+
Dict,
5+
Type,
6+
Tuple,
7+
Union,
8+
NoReturn,
9+
Iterable,
10+
List,
11+
TypeVar,
12+
Generic,
13+
)
14+
15+
from .context import context
16+
from .context import get_boolean
17+
from .context import get_number
18+
from .context import get_object
19+
from .context import get_text
520
from .context import object_name
621
from .context import property_constant_name
22+
from .context import property_constant_number
723
from .context import property_name
824
from .context import query_type
9-
from .generic_object import BaseObject, GenericObject, PropertyTypes
10-
11-
# todo: for the future...
12-
# from .context import get_boolean
13-
# from .context import get_number
14-
# from .context import get_object
15-
# from .context import get_text
16-
# from .context import set_boolean
17-
# from .context import set_number
18-
# from .context import set_object
19-
# from .context import set_text
25+
from .context import set_boolean
26+
from .context import set_number
27+
from .context import set_object
28+
from .context import set_text
29+
from .generic_object import BaseObject, PropertyTypes
2030

2131
registered_objects: Dict[str, Type[BaseObject]] = {}
2232

@@ -65,15 +75,68 @@ def __set__(self, instance: BaseObject, value: PropertyTypes) -> None:
6575
instance.set_property(self.property_number, value)
6676

6777

68-
class Subobjects:
69-
def __init__(self, property_number: int, prop_name: str) -> None:
70-
self.property_number, self.property_name = property_number, prop_name
78+
class Text:
79+
def __init__(self, constant: str):
80+
self.constant = constant
81+
82+
def __get__(self, instance: BaseObject, owner: Type[BaseObject]) -> str:
83+
return (
84+
get_text(instance, property_constant_number(self.constant)) or b""
85+
).decode(context.encoding)
86+
87+
def __set__(self, instance: BaseObject, value: str) -> None:
88+
set_text(
89+
instance,
90+
property_constant_number(self.constant),
91+
value.encode(context.encoding),
92+
)
93+
94+
95+
class Bool:
96+
def __init__(self, constant: str):
97+
self.constant = constant
98+
99+
def __get__(self, instance: BaseObject, owner: Type[BaseObject]) -> bool:
100+
return get_boolean(instance, property_constant_number(self.constant))
101+
102+
def __set__(self, instance: BaseObject, value: bool) -> None:
103+
set_boolean(instance, property_constant_number(self.constant), value)
104+
105+
106+
class Number:
107+
def __init__(self, constant: str):
108+
self.constant = constant
109+
110+
def __get__(self, instance: BaseObject, owner: Type[BaseObject]) -> int:
111+
return get_number(instance, property_constant_number(self.constant))
112+
113+
def __set__(self, instance: BaseObject, value: int) -> None:
114+
set_number(instance, property_constant_number(self.constant), value)
115+
116+
117+
class Object:
118+
def __init__(self, constant: str):
119+
self.constant = constant
120+
121+
def __get__(self, instance: BaseObject, owner: Type[BaseObject]) -> BaseObject:
122+
return BaseObject(get_object(instance, property_constant_number(self.constant)))
123+
124+
def __set__(self, instance: BaseObject, value: BaseObject) -> None:
125+
set_object(instance, property_constant_number(self.constant), value)
126+
127+
128+
T = TypeVar("T")
129+
130+
131+
class Subobjects(Generic[T]):
132+
def __init__(self, constant: str) -> None:
133+
self.constant = constant
71134

72-
def __get__(
73-
self, instance: BaseObject, owner: Type[BaseObject]
74-
) -> List[BaseObject]:
75-
def gen_subobjects() -> Iterable[BaseObject]:
76-
first_child: c_void_p = instance.get_property(self.property_number)
135+
def __get__(self, instance: BaseObject, owner: Type[BaseObject]) -> List[T]:
136+
def gen_subobjects() -> Iterable[T]:
137+
first_child: c_void_p = instance.get_property(
138+
property_constant_number(self.constant)
139+
)
77140
if first_child:
78141
obj_name = object_name(query_type(first_child))
79142
klass = registered_objects[obj_name]
@@ -85,7 +148,7 @@ def gen_subobjects() -> Iterable[BaseObject]:
85148
subobjects = list(gen_subobjects())
86149
return subobjects
87150

88-
def __set__(self, instance: BaseObject, value: None) -> NoReturn:
151+
def __set__(self, instance: BaseObject, value: List[T]) -> NoReturn:
89152
raise AttributeError("can't set attribute")
90153

91154

@@ -103,7 +166,7 @@ def property_attribute(property_number: int) -> Tuple[str, Union[Property, Subob
103166
return prop_name, Property(property_number)
104167
else:
105168
prop_name = obj_property.name
106-
return prop_name, Subobjects(property_number, prop_name)
169+
return prop_name, Subobjects(property_constant_name(property_number))
107170

108171

109172
def object_type(cls: Type[BaseObject], api_objects: Dict) -> Tuple[Dict, int]:

0 commit comments

Comments
 (0)