pycfutils 2024.5.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2024 Cristi Fati
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: pycfutils
3
+ Version: 2024.5.8
4
+ Summary: PyCFUtils (Cristi Fati's Utils for Python (&& more)) - a collection of (cool) scripts / utilities
5
+ Home-page: https://github.com/CristiFati/pycfutils
6
+ Download-URL: https://pypi.org/project/pycfutils
7
+ Author: Cristi Fati
8
+ Author-email: fati_utcluj@yahoo.com
9
+ Maintainer: Cristi Fati
10
+ Maintainer-email: fati_utcluj@yahoo.com
11
+ License: MIT
12
+ Platform: All
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX
18
+ Classifier: Operating System :: Unix
19
+ Classifier: Programming Language :: C
20
+ Classifier: Programming Language :: C++
21
+ Classifier: Programming Language :: Python
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Topic :: Software Development
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+
27
+ # *PyCFUtils*
28
+
29
+ *PyCFUtils* (**C**risti **F**ati's ***Utils*** for ***Py**thon* (&& more)) - a collection of (cool) scripts / utilities
30
+
31
+
32
+ ## Install
33
+
34
+ Use *PIP*:
35
+
36
+ ```shell
37
+ python -m pip install --upgrade pycfutils
38
+ ```
39
+
40
+
41
+ ## Usage example
42
+
43
+ ```python
44
+ import pycfutils.common
45
+ import pycfutils.keyboard
46
+
47
+ print("Press a key...")
48
+ print(pycfutils.keyboard.read_key())
49
+ print(pycfutils.common.timestamp_string(human_readable=True))
50
+
51
+ # --- Windows only ---
52
+ import pycfutils.gui
53
+
54
+ pycfutils.gui.message_box("Title", "Text to display", 200, 200)
55
+ ```
56
+
@@ -0,0 +1,30 @@
1
+ # *PyCFUtils*
2
+
3
+ *PyCFUtils* (**C**risti **F**ati's ***Utils*** for ***Py**thon* (&& more)) - a collection of (cool) scripts / utilities
4
+
5
+
6
+ ## Install
7
+
8
+ Use *PIP*:
9
+
10
+ ```shell
11
+ python -m pip install --upgrade pycfutils
12
+ ```
13
+
14
+
15
+ ## Usage example
16
+
17
+ ```python
18
+ import pycfutils.common
19
+ import pycfutils.keyboard
20
+
21
+ print("Press a key...")
22
+ print(pycfutils.keyboard.read_key())
23
+ print(pycfutils.common.timestamp_string(human_readable=True))
24
+
25
+ # --- Windows only ---
26
+ import pycfutils.gui
27
+
28
+ pycfutils.gui.message_box("Title", "Text to display", 200, 200)
29
+ ```
30
+
@@ -0,0 +1 @@
1
+ # @TODO - cfati: Dummy file - dir is picked up by setuptools.find_packages
@@ -0,0 +1,64 @@
1
+ import math
2
+ import sys
3
+ import time
4
+ from datetime import datetime
5
+ from typing import Sequence, Tuple, Union
6
+
7
+ __all__ = (
8
+ "int_format",
9
+ "timestamp_string",
10
+ "dimensions_2d",
11
+ "uniques",
12
+ )
13
+
14
+
15
+ def int_format(limit: int) -> str:
16
+ sgn = 1 if limit < 0 else 0
17
+ return f"{{:0{math.ceil(math.log10(max(abs(limit), 2))) + sgn:d}d}}"
18
+
19
+
20
+ def timestamp_string(
21
+ timestamp: Union[None, int, float, Sequence] = None,
22
+ human_readable: bool = False,
23
+ date_separator: str = "-",
24
+ time_separator: str = ":",
25
+ separator: str = " ",
26
+ ) -> str:
27
+ tm = (
28
+ time.gmtime(timestamp)
29
+ if timestamp is None or isinstance(timestamp, (int, float))
30
+ else timestamp.timetuple()
31
+ if isinstance(timestamp, datetime)
32
+ else timestamp
33
+ )[:6]
34
+ if human_readable:
35
+ return (
36
+ f"{tm[0]:04d}{date_separator}"
37
+ f"{tm[1]:02d}{date_separator}"
38
+ f"{tm[2]:02d}{separator}"
39
+ f"{tm[3]:02d}{time_separator}"
40
+ f"{tm[4]:02d}{time_separator}{tm[5]:02d}"
41
+ )
42
+ return f"{tm[0]:04d}{tm[1]:02d}{tm[2]:02d}{tm[3]:02d}{tm[4]:02d}{tm[5]:02d}"
43
+
44
+
45
+ def dimensions_2d(n: int) -> Tuple:
46
+ if n <= 0:
47
+ return 0, 0
48
+ sq = round(math.sqrt(n))
49
+ return sq, math.ceil(n / sq)
50
+
51
+
52
+ def uniques(sequence: Sequence) -> Sequence:
53
+ ret = []
54
+ handled = set()
55
+ for e in sequence:
56
+ if e not in handled:
57
+ ret.append(e)
58
+ handled.add(e)
59
+ return ret if isinstance(sequence, list) else tuple(ret)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ print("This script is not meant to be run directly.\n")
64
+ sys.exit(-1)
@@ -0,0 +1,119 @@
1
+ import ctypes as cts
2
+ import sys
3
+ from typing import Any, Optional
4
+
5
+ cts.c_bool = 1
6
+ try:
7
+ _CLS_CDATA = cts.c_int.__mro__[-2]
8
+ except Exception:
9
+ _CLS_CDATA = None
10
+
11
+
12
+ __all__ = ("to_string",)
13
+
14
+
15
+ def _to_string(
16
+ obj: Any,
17
+ indent: int,
18
+ prefix: Optional[str],
19
+ suffix: Optional[str],
20
+ indent_text: str,
21
+ indent_first_line: bool,
22
+ ) -> str:
23
+ cls = obj.__class__
24
+ ret = [prefix] if prefix is not None else []
25
+ ret.append(f"{(indent_text * indent) if indent_first_line else '':s}{obj}")
26
+ if _CLS_CDATA is None or not issubclass(cls, _CLS_CDATA):
27
+ if suffix is not None:
28
+ ret.append(suffix)
29
+ return "\n".join(ret)
30
+ if issubclass(cls, (cts.Structure, cts.Union)):
31
+ for name, _ in obj._fields_:
32
+ ret.append(
33
+ "{:s}{:s}: {:s}".format(
34
+ indent_text * (indent + 1),
35
+ name,
36
+ _to_string(
37
+ obj=getattr(obj, name),
38
+ indent=indent + 1,
39
+ prefix=None,
40
+ suffix=None,
41
+ indent_text=indent_text,
42
+ indent_first_line=False,
43
+ ),
44
+ )
45
+ )
46
+ elif issubclass(cls, cts.Array):
47
+ for e in obj:
48
+ ret.append(
49
+ _to_string(
50
+ obj=e,
51
+ indent=indent + 1,
52
+ prefix=None,
53
+ suffix=None,
54
+ indent_text=indent_text,
55
+ indent_first_line=True,
56
+ )
57
+ )
58
+ elif issubclass(cls, cts._Pointer):
59
+ if obj:
60
+ ret.append(
61
+ _to_string(
62
+ obj=obj.contents,
63
+ indent=indent + 1,
64
+ prefix=prefix,
65
+ suffix=suffix,
66
+ indent_text=indent_text,
67
+ indent_first_line=True,
68
+ )
69
+ )
70
+ if suffix is not None:
71
+ ret.append(suffix)
72
+ return "\n".join(ret)
73
+
74
+
75
+ def to_string(
76
+ obj: Any,
77
+ indent: int = 0,
78
+ prefix: Optional[str] = "",
79
+ suffix: Optional[str] = "",
80
+ indent_text: str = " ",
81
+ ) -> str:
82
+ return _to_string(
83
+ obj=obj,
84
+ indent=indent,
85
+ prefix=prefix,
86
+ suffix=suffix,
87
+ indent_text=indent_text,
88
+ indent_first_line=True,
89
+ )
90
+
91
+
92
+ if _CLS_CDATA:
93
+ __all__ += (
94
+ "Structure",
95
+ "Union",
96
+ # "Array",
97
+ "BigEndianStructure",
98
+ "LittleEndianStructure",
99
+ )
100
+
101
+ class Structure(cts.Structure):
102
+ to_string = to_string
103
+
104
+ class Union(cts.Union):
105
+ to_string = to_string
106
+
107
+ # class Array(cts.Array):
108
+ # to_string = to_string
109
+
110
+ class BigEndianStructure(cts.BigEndianStructure):
111
+ to_string = to_string
112
+
113
+ class LittleEndianStructure(cts.LittleEndianStructure):
114
+ to_string = to_string
115
+
116
+
117
+ if __name__ == "__main__":
118
+ print("This script is not meant to be run directly.\n")
119
+ sys.exit(-1)
@@ -0,0 +1,66 @@
1
+ import atexit
2
+ import ctypes as cts
3
+ import os
4
+ import sys
5
+ from typing import Optional
6
+
7
+ __all__ = ()
8
+
9
+ _IS_WIN = sys.platform[:3].lower() == "win"
10
+ _DLL_NAME = os.path.join(
11
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
12
+ f"libcinterface.{'dll' if _IS_WIN else 'so'}",
13
+ )
14
+
15
+ if _IS_WIN:
16
+ from ctypes import wintypes as wts
17
+
18
+ __all__ += ("message_box",)
19
+
20
+ _DLL = cts.CDLL(_DLL_NAME)
21
+
22
+ _MessageBoxXY = _DLL.MessageBoxXY
23
+ _MessageBoxXY.argtypes = (
24
+ wts.HWND,
25
+ wts.LPCWSTR,
26
+ wts.LPCWSTR,
27
+ wts.UINT,
28
+ cts.c_int,
29
+ cts.c_int,
30
+ )
31
+ _MessageBoxXY.restype = cts.c_int
32
+
33
+ def message_box(
34
+ title: str,
35
+ text: str,
36
+ x: Optional[int] = None,
37
+ y: Optional[int] = None,
38
+ style: int = 0,
39
+ hwnd: Optional[wts.HWND] = None,
40
+ ) -> int:
41
+ return _MessageBoxXY(
42
+ hwnd,
43
+ text,
44
+ title,
45
+ style,
46
+ x if x is not None else 0x80000000,
47
+ y if y is not None else 0x80000000,
48
+ )
49
+
50
+ _clearHooks = _DLL.clearHooks
51
+ _clearHooks.argtypes = ()
52
+ _clearHooks.restype = cts.c_int
53
+ atexit.register(_clearHooks)
54
+ del _clearHooks
55
+ else: # Nix
56
+ _DLL = None
57
+
58
+
59
+ del _DLL
60
+ del _DLL_NAME
61
+ del _IS_WIN
62
+
63
+
64
+ if __name__ == "__main__":
65
+ print("This script is not meant to be run directly.\n")
66
+ sys.exit(-1)
@@ -0,0 +1,81 @@
1
+ """
2
+ Module containing package constants.
3
+
4
+ NOTE:
5
+ Due to the fact that for MessageBox there had to be added ~50 of them,
6
+ it's not scalable, so they (or the entire module)
7
+ might be removed in the future.
8
+
9
+ Please use some specialized packages (if any) that export them.
10
+ For MessageBox, win32con can be used (https://github.com/mhammond/pywin32).
11
+
12
+ """
13
+ import sys
14
+ import warnings
15
+
16
+ warnings.warn("This module might be removed in the future")
17
+
18
+ __IS_WIN = sys.platform[:3].lower() == "win"
19
+
20
+ if __IS_WIN:
21
+ MB_OK = 0x00000000
22
+ MB_OKCANCEL = 0x00000001
23
+ MB_ABORTRETRYIGNORE = 0x00000002
24
+ MB_YESNOCANCEL = 0x00000003
25
+ MB_YESNO = 0x00000004
26
+ MB_RETRYCANCEL = 0x00000005
27
+ MB_CANCELTRYCONTINUE = 0x00000006
28
+ MB_ICONHAND = 0x00000010
29
+ MB_ICONQUESTION = 0x00000020
30
+ MB_ICONEXCLAMATION = 0x00000030
31
+ MB_ICONASTERISK = 0x00000040
32
+ MB_USERICON = 0x00000080
33
+ MB_ICONWARNING = MB_ICONEXCLAMATION
34
+ MB_ICONERROR = MB_ICONHAND
35
+ MB_ICONINFORMATION = MB_ICONASTERISK
36
+ MB_ICONSTOP = MB_ICONHAND
37
+ MB_DEFBUTTON1 = 0x00000000
38
+ MB_DEFBUTTON2 = 0x00000100
39
+ MB_DEFBUTTON3 = 0x00000200
40
+ MB_DEFBUTTON4 = 0x00000300
41
+ MB_APPLMODAL = 0x00000000
42
+ MB_SYSTEMMODAL = 0x00001000
43
+ MB_TASKMODAL = 0x00002000
44
+ MB_HELP = 0x00004000
45
+ MB_NOFOCUS = 0x00008000
46
+ MB_SETFOREGROUND = 0x00010000
47
+ MB_DEFAULT_DESKTOP_ONLY = 0x00020000
48
+ MB_TOPMOST = 0x00040000
49
+ MB_RIGHT = 0x00080000
50
+ MB_RTLREADING = 0x00100000
51
+ MB_SERVICE_NOTIFICATION = 0x00200000
52
+ MB_SERVICE_NOTIFICATION = 0x00040000
53
+ MB_SERVICE_NOTIFICATION_NT3X = 0x00040000
54
+ MB_TYPEMASK = 0x0000000F
55
+ MB_ICONMASK = 0x000000F0
56
+ MB_DEFMASK = 0x00000F00
57
+ MB_MODEMASK = 0x00003000
58
+ MB_MISCMASK = 0x0000C000
59
+
60
+ IDOK = 1
61
+ IDCANCEL = 2
62
+ IDABORT = 3
63
+ IDRETRY = 4
64
+ IDIGNORE = 5
65
+ IDYES = 6
66
+ IDNO = 7
67
+ IDCLOSE = 8
68
+ IDHELP = 9
69
+ IDTRYAGAIN = 10
70
+ IDCONTINUE = 11
71
+ IDTIMEOUT = 32000
72
+
73
+ # else: # Nix
74
+
75
+
76
+ del __IS_WIN
77
+
78
+
79
+ if __name__ == "__main__":
80
+ print("This script is not meant to be run directly.\n")
81
+ sys.exit(-1)
@@ -0,0 +1,38 @@
1
+ // LibCInterface prototypes
2
+ #pragma once
3
+
4
+ #if defined(_WIN32)
5
+ # if defined(LIBCINTERFACE_STATIC)
6
+ # define LIBCINTERFACE_EXPORT_API
7
+ # else // LIBCINTERFACE_STATIC
8
+ # if defined(LIBCINTERFACE_EXPORTS)
9
+ # define LIBCINTERFACE_EXPORT_API __declspec(dllexport)
10
+ # else // LIBCINTERFACE_EXPORTS
11
+ # define LIBCINTERFACE_EXPORT_API __declspec(dllimport)
12
+ # endif // LIBCINTERFACE_EXPORTS
13
+ # endif // LIBCINTERFACE_STATIC
14
+ #else // _WIN32
15
+ # define LIBCINTERFACE_EXPORT_API
16
+ #endif // _WIN32
17
+
18
+ #if defined(_WIN32)
19
+ # include <Windows.h>
20
+ #else // _WIN32
21
+ #endif // _WIN32
22
+
23
+ #if defined(__cplusplus)
24
+ extern "C" {
25
+ #endif // __cplusplus
26
+
27
+ # if defined(_WIN32)
28
+
29
+ LIBCINTERFACE_EXPORT_API int MessageBoxXY(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, int x, int y);
30
+ LIBCINTERFACE_EXPORT_API int clearHooks();
31
+
32
+ # else // _WIN32
33
+ # endif // _WIN32
34
+
35
+ #if defined(__cplusplus)
36
+ }
37
+ #endif // __cplusplus
38
+
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python
2
+
3
+ import functools
4
+ import sys
5
+ import time
6
+ from typing import Any, Callable, Optional
7
+
8
+ __all__ = ("read_key",)
9
+
10
+
11
+ def _read_key(
12
+ interval: float = 0.5,
13
+ poll_interval: float = 0.1,
14
+ kp_func: Optional[Callable[[], bool]] = None,
15
+ rk_func: Optional[Callable[[], int]] = None,
16
+ start_func: Optional[Callable[[], Any]] = None,
17
+ end_func: Optional[Callable[[Any], None]] = None,
18
+ ):
19
+ ctx = start_func() if start_func is not None else None
20
+ try:
21
+ poll_interval = (
22
+ interval / 2.0 if poll_interval > interval / 2.0 else poll_interval
23
+ )
24
+ time_end = time.time() + interval
25
+ while True:
26
+ if kp_func is not None and kp_func():
27
+ return rk_func() if rk_func is not None else None
28
+ if time.time() >= time_end:
29
+ break
30
+ time.sleep(poll_interval)
31
+ return None
32
+ finally:
33
+ if end_func is not None:
34
+ end_func(ctx)
35
+
36
+
37
+ if sys.platform[:3].lower() == "win":
38
+ import msvcrt
39
+
40
+ def _key_pressed_func() -> bool:
41
+ return msvcrt.kbhit()
42
+
43
+ def _read_key_func() -> int:
44
+ return ord(msvcrt.getch())
45
+
46
+ _start_func = None
47
+ _end_func = None
48
+
49
+
50
+ else: # Nix
51
+ import select
52
+ import termios
53
+ import tty
54
+
55
+ def _key_pressed_func() -> bool:
56
+ return sys.stdin in select.select([sys.stdin], [], [], 0)[0]
57
+
58
+ def _read_key_func() -> int:
59
+ return ord(sys.stdin.read(1))
60
+
61
+ def _start_func() -> Any:
62
+ attrs = termios.tcgetattr(sys.stdin)
63
+ tty.setcbreak(sys.stdin.fileno(), when=termios.TCSAFLUSH)
64
+ return attrs
65
+
66
+ def _end_func(attrs) -> None:
67
+ if attrs is not None:
68
+ termios.tcsetattr(sys.stdin, termios.TCSADRAIN, attrs)
69
+
70
+
71
+ read_key = functools.partial(
72
+ _read_key,
73
+ kp_func=_key_pressed_func,
74
+ rk_func=_read_key_func,
75
+ start_func=_start_func,
76
+ end_func=_end_func,
77
+ )
78
+
79
+ del _end_func
80
+ del _start_func
81
+ del _read_key_func
82
+ del _key_pressed_func
83
+
84
+
85
+ if __name__ == "__main__":
86
+ exit_char = 0x1B # Esc
87
+ print(f"Looping till 0x{exit_char:02X} is pressed")
88
+ while 1:
89
+ k = read_key()
90
+ if k is not None:
91
+ print(f"Pressed: 0x{k:02X} ({k:c})")
92
+ if k == exit_char:
93
+ print("Exit\n")
94
+ break
@@ -0,0 +1,122 @@
1
+ #include <unordered_map>
2
+ #include <utility>
3
+ #include <vector>
4
+
5
+ #include <Windows.h>
6
+
7
+ #define LIBCINTERFACE_EXPORTS
8
+ #include "../include/pycfutils/cinterface.h"
9
+
10
+ #define SENTINEL 0x80000000
11
+
12
+
13
+ typedef std::unordered_map<DWORD, HHOOK> HookData;
14
+ typedef std::pair<int, int> XY;
15
+ typedef std::unordered_map<DWORD, std::vector<XY>> XYData;
16
+
17
+ CRITICAL_SECTION criticalSection;
18
+ XYData xyData;
19
+ HookData hookData;
20
+
21
+
22
+ static LRESULT CALLBACK _hookFunc(int nCode, WPARAM wParam, LPARAM lParam)
23
+ {
24
+ if (nCode < 0) {
25
+ return CallNextHookEx(NULL, nCode, wParam, lParam);
26
+ }
27
+ switch (nCode) {
28
+ case HCBT_CREATEWND: {
29
+ EnterCriticalSection(&criticalSection);
30
+ DWORD tid = GetCurrentThreadId();
31
+ if (hookData.find(tid) != hookData.cend()) {
32
+ auto xyIt = xyData[tid].cbegin();
33
+ if (xyIt != xyData[tid].cend()) {
34
+ LPCBT_CREATEWNDW pcw = (LPCBT_CREATEWNDW)lParam;
35
+ if (pcw) {
36
+ LPCREATESTRUCTW pcs = pcw->lpcs;
37
+ if (pcs) {
38
+ if (xyIt->first != SENTINEL) {
39
+ pcs->x = xyIt->first;
40
+ }
41
+ if (xyIt->second != SENTINEL) {
42
+ pcs->y = xyIt->second;
43
+ }
44
+ }
45
+ }
46
+ xyData[tid].erase(xyIt);
47
+ }
48
+ }
49
+ LeaveCriticalSection(&criticalSection);
50
+ break;
51
+ }
52
+ default: {
53
+ break;
54
+ }
55
+ }
56
+ return CallNextHookEx(NULL, nCode, wParam, lParam);
57
+ }
58
+
59
+ int MessageBoxXY(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, int x, int y)
60
+ {
61
+ EnterCriticalSection(&criticalSection);
62
+ DWORD tid = GetCurrentThreadId();
63
+ if (hookData.find(tid) == hookData.cend()) {
64
+ HHOOK hook = SetWindowsHookExW(WH_CBT, _hookFunc, 0, tid);
65
+ if (hook) {
66
+ hookData[tid] = hook;
67
+ } // @TODO - cfati: Silently fail?
68
+ }
69
+ xyData[tid].emplace_back(std::make_pair(x, y));
70
+ LeaveCriticalSection(&criticalSection);
71
+ return MessageBoxW(hWnd, lpText, lpCaption, uType);
72
+ }
73
+
74
+
75
+ int clearHooks()
76
+ {
77
+ int ret = 0;
78
+ EnterCriticalSection(&criticalSection);
79
+ for (auto it = hookData.cbegin(); it != hookData.cend(); ++it) {
80
+ if (UnhookWindowsHookEx(it->second)) {
81
+ ++ret;
82
+ } // @TODO - cfati: Silently fail?
83
+ }
84
+ LeaveCriticalSection(&criticalSection);
85
+ return ret;
86
+ }
87
+
88
+
89
+ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
90
+ {
91
+ // Perform actions based on the reason for calling.
92
+ switch (fdwReason) {
93
+ case DLL_PROCESS_ATTACH: {
94
+ // Initialize once for each new process.
95
+ // Return FALSE to fail DLL load.
96
+ InitializeCriticalSection(&criticalSection);
97
+ break;
98
+ }
99
+ case DLL_THREAD_ATTACH: {
100
+ // Do thread-specific initialization.
101
+ break;
102
+ }
103
+ case DLL_THREAD_DETACH: {
104
+ // Do thread-specific cleanup.
105
+ break;
106
+ }
107
+ case DLL_PROCESS_DETACH: {
108
+
109
+ if (lpvReserved != NULL) {
110
+ break; // do not do cleanup if process termination scenario
111
+ }
112
+ DeleteCriticalSection(&criticalSection);
113
+ // Perform any necessary cleanup.
114
+ break;
115
+ }
116
+ default: {
117
+ break;
118
+ }
119
+ }
120
+ return TRUE; // Successful DLL_PROCESS_ATTACH.
121
+ }
122
+
@@ -0,0 +1 @@
1
+ # @TODO - cfati: Dummy file - dir is picked up by setuptools.find_packages
@@ -0,0 +1,57 @@
1
+ import unittest
2
+ from datetime import datetime
3
+
4
+ from pycfutils import common
5
+
6
+
7
+ class CommonTestCase(unittest.TestCase):
8
+ def test_int_format(self):
9
+ self.assertEqual(common.int_format(-101), "{:04d}")
10
+ self.assertEqual(common.int_format(-100), "{:03d}")
11
+ self.assertEqual(common.int_format(-11), "{:03d}")
12
+ self.assertEqual(common.int_format(-10), "{:02d}")
13
+ self.assertEqual(common.int_format(-1), "{:02d}")
14
+ self.assertEqual(common.int_format(0), "{:01d}")
15
+ self.assertEqual(common.int_format(1), "{:01d}")
16
+ self.assertEqual(common.int_format(10), "{:01d}")
17
+ self.assertEqual(common.int_format(11), "{:02d}")
18
+ self.assertEqual(common.int_format(100), "{:02d}")
19
+ self.assertEqual(common.int_format(101), "{:03d}")
20
+
21
+ def test_timestamp_string(self):
22
+ ts = (2024, 5, 6, 12, 34, 56)
23
+ self.assertEqual(
24
+ common.timestamp_string(timestamp=ts, human_readable=False),
25
+ "20240506123456",
26
+ )
27
+ self.assertEqual(
28
+ common.timestamp_string(timestamp=ts, human_readable=True),
29
+ "2024-05-06 12:34:56",
30
+ )
31
+ self.assertTrue(common.timestamp_string(datetime.now()))
32
+
33
+ def test_uniques(self):
34
+ l0 = [1, 2, 3, 1, 4, 3, 5, 1, 1, 2, 6, 0, 0]
35
+ l1 = [1, 2, 3, 4, 5, 6, 0]
36
+ self.assertEqual(common.uniques([]), [])
37
+ self.assertEqual(common.uniques(()), ())
38
+ self.assertEqual(common.uniques(range(3)), (0, 1, 2))
39
+ self.assertEqual(common.uniques(l0), l1)
40
+ self.assertEqual(common.uniques((e for e in l0)), tuple(l1))
41
+ self.assertEqual(set(common.uniques(set(l0))), set(l0))
42
+
43
+ def test_dimensions2d(self):
44
+ self.assertEqual(common.dimensions_2d(-3), (0, 0))
45
+ self.assertEqual(common.dimensions_2d(0), (0, 0))
46
+ self.assertEqual(common.dimensions_2d(1), (1, 1))
47
+ self.assertEqual(common.dimensions_2d(2), (1, 2))
48
+ self.assertEqual(common.dimensions_2d(3), (2, 2))
49
+ self.assertEqual(common.dimensions_2d(4), (2, 2))
50
+ self.assertEqual(common.dimensions_2d(5), (2, 3))
51
+ self.assertEqual(common.dimensions_2d(6), (2, 3))
52
+ self.assertEqual(common.dimensions_2d(7), (3, 3))
53
+ self.assertEqual(common.dimensions_2d(8), (3, 3))
54
+ self.assertEqual(common.dimensions_2d(9), (3, 3))
55
+ self.assertEqual(common.dimensions_2d(10), (3, 4))
56
+ self.assertEqual(common.dimensions_2d(13), (4, 4))
57
+ self.assertEqual(common.dimensions_2d(20), (4, 5))
@@ -0,0 +1,34 @@
1
+ import ctypes as cts
2
+ import unittest
3
+
4
+ from pycfutils import ctypes
5
+
6
+ FloatArr10 = cts.c_float * 10
7
+
8
+
9
+ class S0(ctypes.Structure):
10
+ _fields_ = (
11
+ ("i", cts.c_int),
12
+ ("s", cts.c_char_p),
13
+ ("fa", FloatArr10),
14
+ ("pi", cts.POINTER(cts.c_int)),
15
+ )
16
+
17
+
18
+ # @TODO - cfati: Dummy-ish
19
+ class CTypesTestCase(unittest.TestCase):
20
+ def test_to_string(self):
21
+ self.assertEqual(ctypes.to_string(1), "\n1\n")
22
+
23
+ def test_structure(self):
24
+ i = cts.c_int(1234)
25
+ s0 = S0(
26
+ -32,
27
+ b"dummy text",
28
+ FloatArr10(*(float(e) for e in range(20, 30))),
29
+ cts.pointer(i),
30
+ )
31
+ s = s0.to_string(suffix=None)
32
+ # print(s)
33
+ self.assertIn("-32", s)
34
+ self.assertIn("dummy text", s)
@@ -0,0 +1,14 @@
1
+ import sys
2
+ import unittest
3
+
4
+ from pycfutils import gui
5
+
6
+
7
+ # @TODO - cfati: Dummy
8
+ class GUITestCase(unittest.TestCase):
9
+ def test_message_box(self):
10
+ message_box_name = "message_box"
11
+ if sys.platform[:3].lower() == "win":
12
+ self.assertIsNotNone(getattr(gui, message_box_name, None))
13
+ else:
14
+ self.assertIsNone(getattr(gui, message_box_name, None))
@@ -0,0 +1,14 @@
1
+ import time
2
+ import unittest
3
+
4
+ from pycfutils import keyboard
5
+
6
+
7
+ class KwyboardTestCase(unittest.TestCase):
8
+ def test_read_key(self):
9
+ itv = 0.5
10
+ pitv = 0.1
11
+ margin = 0.05
12
+ ts = time.time()
13
+ k = keyboard.read_key(interval=itv, poll_interval=pitv)
14
+ self.assertTrue(k is not None or abs(time.time() - ts - itv) < pitv + margin)
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: pycfutils
3
+ Version: 2024.5.8
4
+ Summary: PyCFUtils (Cristi Fati's Utils for Python (&& more)) - a collection of (cool) scripts / utilities
5
+ Home-page: https://github.com/CristiFati/pycfutils
6
+ Download-URL: https://pypi.org/project/pycfutils
7
+ Author: Cristi Fati
8
+ Author-email: fati_utcluj@yahoo.com
9
+ Maintainer: Cristi Fati
10
+ Maintainer-email: fati_utcluj@yahoo.com
11
+ License: MIT
12
+ Platform: All
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX
18
+ Classifier: Operating System :: Unix
19
+ Classifier: Programming Language :: C
20
+ Classifier: Programming Language :: C++
21
+ Classifier: Programming Language :: Python
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Topic :: Software Development
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+
27
+ # *PyCFUtils*
28
+
29
+ *PyCFUtils* (**C**risti **F**ati's ***Utils*** for ***Py**thon* (&& more)) - a collection of (cool) scripts / utilities
30
+
31
+
32
+ ## Install
33
+
34
+ Use *PIP*:
35
+
36
+ ```shell
37
+ python -m pip install --upgrade pycfutils
38
+ ```
39
+
40
+
41
+ ## Usage example
42
+
43
+ ```python
44
+ import pycfutils.common
45
+ import pycfutils.keyboard
46
+
47
+ print("Press a key...")
48
+ print(pycfutils.keyboard.read_key())
49
+ print(pycfutils.common.timestamp_string(human_readable=True))
50
+
51
+ # --- Windows only ---
52
+ import pycfutils.gui
53
+
54
+ pycfutils.gui.message_box("Title", "Text to display", 200, 200)
55
+ ```
56
+
@@ -0,0 +1,23 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ pycfutils/__init__.py
5
+ pycfutils/common.py
6
+ pycfutils/ctypes.py
7
+ pycfutils/keyboard.py
8
+ pycfutils.egg-info/PKG-INFO
9
+ pycfutils.egg-info/SOURCES.txt
10
+ pycfutils.egg-info/dependency_links.txt
11
+ pycfutils.egg-info/top_level.txt
12
+ pycfutils/gui/__init__.py
13
+ pycfutils/gui/constants.py
14
+ pycfutils/tests/__init__.py
15
+ pycfutils/tests/test_common.py
16
+ pycfutils/tests/test_ctypes.py
17
+ pycfutils/tests/test_gui.py
18
+ pycfutils/tests/test_keyboard.py
19
+ vs/vs.vcxproj
20
+ vs/vs.vcxproj.filters
21
+ vs/vs.sln
22
+ pycfutils/include/pycfutils/cinterface.h
23
+ pycfutils/src/cinterface_win.cpp
@@ -0,0 +1 @@
1
+ pycfutils
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ Still using setup.py, as I didn't get up to speed with pyproject.toml,
5
+ especially due to the workarounds (some quite lame) done to build the .dll.
6
+ """
7
+
8
+ import glob
9
+ import os
10
+ import sys
11
+
12
+ from setuptools import find_packages, setup
13
+ from setuptools.command.build_ext import build_ext
14
+ from setuptools.command.sdist import sdist
15
+ from setuptools.extension import Library
16
+ from wheel.bdist_wheel import bdist_wheel
17
+
18
+ _IS_WIN = sys.platform[:3].lower() == "win"
19
+
20
+ _NAME = "pycfutils"
21
+ _VERSION = "2024.05.08"
22
+
23
+ if _IS_WIN:
24
+ _EXT = ".dll"
25
+ _SUF = "win"
26
+ else:
27
+ _EXT = ".so"
28
+ _SUF = "nix"
29
+
30
+ _INCLUDE_DIR = f"include/{_NAME}"
31
+ _INCLUDE_FILES = (f"{_INCLUDE_DIR}/cinterface.h",)
32
+ _SOURCE_FILES = [
33
+ e.replace("\\", "/")
34
+ for e in glob.glob(os.path.join(_NAME, "src", f"cinterface_*.cpp"))
35
+ ]
36
+ _VS_FILES = tuple(
37
+ f"vs/{e}"
38
+ for e in (
39
+ "vs.vcxproj",
40
+ "vs.vcxproj.filters",
41
+ "vs.sln",
42
+ )
43
+ )
44
+
45
+
46
+ # @TODO - cfati (gainarie): Get rid of sysconfig's EXT_SUFFIX (e.g.: .cp310-win_amd64)
47
+ class BuildDll(build_ext):
48
+ def get_ext_filename(self, ext_name):
49
+ return os.path.join(*ext_name.split(".")) + _EXT
50
+
51
+
52
+ # @TODO - cfati (gainarie): Create generic .whl as the .dll doesn't depend on Python
53
+ class BDistWheelDll(bdist_wheel):
54
+ def get_tag(self):
55
+ if _IS_WIN:
56
+ plat = self.plat_name.replace("-", "_").replace(".", "_").replace(" ", "_")
57
+ else:
58
+ plat = "any"
59
+ return (
60
+ "py3",
61
+ "none",
62
+ plat,
63
+ )
64
+
65
+
66
+ # @TODO - cfati (gainarie): Manually add files in the source distribution (built on Nix)
67
+ class SDist(sdist):
68
+ @staticmethod
69
+ def _extra_files():
70
+ ret = list(_VS_FILES)
71
+ if _IS_WIN:
72
+ return ret
73
+ ret.extend((os.path.join(_NAME, e) for e in _INCLUDE_FILES))
74
+ ret.extend(_SOURCE_FILES)
75
+ return ret
76
+
77
+ def _adjust_sources(self):
78
+ ei_cmd = super().get_finalized_command("egg_info")
79
+ manifest = os.path.join(ei_cmd.egg_info, "SOURCES.txt")
80
+ existing = [e.rstrip() for e in open(manifest).readlines()]
81
+ modified = False
82
+ for file in self._extra_files():
83
+ if file not in existing:
84
+ modified = True
85
+ existing.append(file)
86
+ if modified:
87
+ with open(manifest, mode="w") as f:
88
+ f.writelines((f"{e}\n" for e in existing))
89
+
90
+ def get_finalized_command(self, command, create=1):
91
+ cmd = super().get_finalized_command(command, create=create)
92
+ extra = self._extra_files()
93
+ if extra:
94
+ cmd.filelist.files.extend(extra)
95
+ self._adjust_sources()
96
+ return cmd
97
+
98
+
99
+ c_interface_dll = Library(
100
+ (_NAME + ".libcinterface"),
101
+ sources=_SOURCE_FILES,
102
+ include_dirs=[f"{_NAME}/include"],
103
+ define_macros=[
104
+ ("UNICODE", None),
105
+ ("_UNICODE", None),
106
+ ("WIN32", None),
107
+ ("_WINDLL", None),
108
+ ],
109
+ extra_link_args=[
110
+ "/DLL",
111
+ ],
112
+ libraries=[
113
+ "user32",
114
+ "kernel32",
115
+ ],
116
+ )
117
+
118
+ setup_args = dict(
119
+ name=_NAME,
120
+ version=_VERSION,
121
+ description="PyCFUtils (Cristi Fati's Utils for Python (&& more)) - "
122
+ "a collection of (cool) scripts / utilities",
123
+ long_description=open("README.md").read(),
124
+ long_description_content_type="text/markdown",
125
+ author="Cristi Fati",
126
+ author_email="fati_utcluj@yahoo.com",
127
+ maintainer="Cristi Fati",
128
+ maintainer_email="fati_utcluj@yahoo.com",
129
+ classifiers=[
130
+ "Development Status :: 5 - Production/Stable",
131
+ "License :: OSI Approved :: MIT License",
132
+ "Operating System :: MacOS",
133
+ "Operating System :: Microsoft :: Windows",
134
+ "Operating System :: POSIX",
135
+ "Operating System :: Unix",
136
+ "Programming Language :: C",
137
+ "Programming Language :: C++",
138
+ "Programming Language :: Python",
139
+ "Programming Language :: Python :: 3 :: Only",
140
+ "Topic :: Software Development",
141
+ ],
142
+ platforms=("All",),
143
+ license="MIT",
144
+ url=f"https://github.com/CristiFati/{_NAME}",
145
+ download_url=f"https://pypi.org/project/{_NAME}",
146
+ packages=find_packages(
147
+ include=(f"{_NAME}", f"{_NAME}.gui", f"{_NAME}.tests"),
148
+ exclude=("src", "__pycache__"),
149
+ ),
150
+ package_data={
151
+ f"{_NAME}": _INCLUDE_FILES if _IS_WIN else (),
152
+ },
153
+ cmdclass={
154
+ "build_ext": BuildDll,
155
+ "bdist_wheel": BDistWheelDll,
156
+ "sdist": SDist,
157
+ },
158
+ ext_modules=[c_interface_dll] if _IS_WIN else [],
159
+ )
160
+
161
+ setup(**setup_args)
@@ -0,0 +1,31 @@
1
+ 
2
+ Microsoft Visual Studio Solution File, Format Version 12.00
3
+ # Visual Studio Version 16
4
+ VisualStudioVersion = 16.0.34729.46
5
+ MinimumVisualStudioVersion = 10.0.40219.1
6
+ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vs", "vs.vcxproj", "{E67CC532-0677-49C4-95AD-0FEFDCA7865D}"
7
+ EndProject
8
+ Global
9
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
10
+ Debug|x64 = Debug|x64
11
+ Debug|x86 = Debug|x86
12
+ Release|x64 = Release|x64
13
+ Release|x86 = Release|x86
14
+ EndGlobalSection
15
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
16
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Debug|x64.ActiveCfg = Debug|x64
17
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Debug|x64.Build.0 = Debug|x64
18
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Debug|x86.ActiveCfg = Debug|Win32
19
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Debug|x86.Build.0 = Debug|Win32
20
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Release|x64.ActiveCfg = Release|x64
21
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Release|x64.Build.0 = Release|x64
22
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Release|x86.ActiveCfg = Release|Win32
23
+ {E67CC532-0677-49C4-95AD-0FEFDCA7865D}.Release|x86.Build.0 = Release|Win32
24
+ EndGlobalSection
25
+ GlobalSection(SolutionProperties) = preSolution
26
+ HideSolutionNode = FALSE
27
+ EndGlobalSection
28
+ GlobalSection(ExtensibilityGlobals) = postSolution
29
+ SolutionGuid = {54F052B3-B473-45EE-B8F2-F621E5EEB6C3}
30
+ EndGlobalSection
31
+ EndGlobal
@@ -0,0 +1,167 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+ <ItemGroup Label="ProjectConfigurations">
4
+ <ProjectConfiguration Include="Debug|Win32">
5
+ <Configuration>Debug</Configuration>
6
+ <Platform>Win32</Platform>
7
+ </ProjectConfiguration>
8
+ <ProjectConfiguration Include="Release|Win32">
9
+ <Configuration>Release</Configuration>
10
+ <Platform>Win32</Platform>
11
+ </ProjectConfiguration>
12
+ <ProjectConfiguration Include="Debug|x64">
13
+ <Configuration>Debug</Configuration>
14
+ <Platform>x64</Platform>
15
+ </ProjectConfiguration>
16
+ <ProjectConfiguration Include="Release|x64">
17
+ <Configuration>Release</Configuration>
18
+ <Platform>x64</Platform>
19
+ </ProjectConfiguration>
20
+ </ItemGroup>
21
+ <PropertyGroup Label="Globals">
22
+ <VCProjectVersion>16.0</VCProjectVersion>
23
+ <Keyword>Win32Proj</Keyword>
24
+ <ProjectGuid>{e67cc532-0677-49c4-95ad-0fefdca7865d}</ProjectGuid>
25
+ <RootNamespace>cinterface</RootNamespace>
26
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
27
+ </PropertyGroup>
28
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
29
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
30
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
31
+ <UseDebugLibraries>true</UseDebugLibraries>
32
+ <PlatformToolset>v142</PlatformToolset>
33
+ <CharacterSet>Unicode</CharacterSet>
34
+ </PropertyGroup>
35
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
36
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
37
+ <UseDebugLibraries>false</UseDebugLibraries>
38
+ <PlatformToolset>v142</PlatformToolset>
39
+ <WholeProgramOptimization>true</WholeProgramOptimization>
40
+ <CharacterSet>Unicode</CharacterSet>
41
+ </PropertyGroup>
42
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
43
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
44
+ <UseDebugLibraries>true</UseDebugLibraries>
45
+ <PlatformToolset>v142</PlatformToolset>
46
+ <CharacterSet>Unicode</CharacterSet>
47
+ </PropertyGroup>
48
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
49
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
50
+ <UseDebugLibraries>false</UseDebugLibraries>
51
+ <PlatformToolset>v142</PlatformToolset>
52
+ <WholeProgramOptimization>true</WholeProgramOptimization>
53
+ <CharacterSet>Unicode</CharacterSet>
54
+ </PropertyGroup>
55
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
56
+ <ImportGroup Label="ExtensionSettings">
57
+ </ImportGroup>
58
+ <ImportGroup Label="Shared">
59
+ </ImportGroup>
60
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
61
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
62
+ </ImportGroup>
63
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
64
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
65
+ </ImportGroup>
66
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
67
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
68
+ </ImportGroup>
69
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
70
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
71
+ </ImportGroup>
72
+ <PropertyGroup Label="UserMacros" />
73
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
74
+ <LinkIncremental>true</LinkIncremental>
75
+ <OutDir>$(SolutionDir)$(Platform)-$(Configuration)\</OutDir>
76
+ <IntDir>$(Platform)-$(Configuration)\</IntDir>
77
+ <TargetName>libcinterface</TargetName>
78
+ </PropertyGroup>
79
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
80
+ <LinkIncremental>false</LinkIncremental>
81
+ <OutDir>$(SolutionDir)$(Platform)-$(Configuration)\</OutDir>
82
+ <IntDir>$(Platform)-$(Configuration)\</IntDir>
83
+ <TargetName>libcinterface</TargetName>
84
+ </PropertyGroup>
85
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
86
+ <LinkIncremental>true</LinkIncremental>
87
+ <OutDir>$(SolutionDir)$(Platform)-$(Configuration)\</OutDir>
88
+ <IntDir>$(Platform)-$(Configuration)\</IntDir>
89
+ <TargetName>libcinterface</TargetName>
90
+ </PropertyGroup>
91
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
92
+ <LinkIncremental>false</LinkIncremental>
93
+ <OutDir>$(SolutionDir)$(Platform)-$(Configuration)\</OutDir>
94
+ <IntDir>$(Platform)-$(Configuration)\</IntDir>
95
+ <TargetName>libcinterface</TargetName>
96
+ </PropertyGroup>
97
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
98
+ <ClCompile>
99
+ <WarningLevel>Level3</WarningLevel>
100
+ <SDLCheck>true</SDLCheck>
101
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
102
+ <ConformanceMode>true</ConformanceMode>
103
+ </ClCompile>
104
+ <Link>
105
+ <SubSystem>Console</SubSystem>
106
+ <GenerateDebugInformation>true</GenerateDebugInformation>
107
+ </Link>
108
+ </ItemDefinitionGroup>
109
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
110
+ <ClCompile>
111
+ <WarningLevel>Level3</WarningLevel>
112
+ <FunctionLevelLinking>true</FunctionLevelLinking>
113
+ <IntrinsicFunctions>true</IntrinsicFunctions>
114
+ <SDLCheck>true</SDLCheck>
115
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
116
+ <ConformanceMode>true</ConformanceMode>
117
+ </ClCompile>
118
+ <Link>
119
+ <SubSystem>Console</SubSystem>
120
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
121
+ <OptimizeReferences>true</OptimizeReferences>
122
+ <GenerateDebugInformation>true</GenerateDebugInformation>
123
+ </Link>
124
+ </ItemDefinitionGroup>
125
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
126
+ <ClCompile>
127
+ <WarningLevel>Level3</WarningLevel>
128
+ <SDLCheck>true</SDLCheck>
129
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
130
+ <ConformanceMode>true</ConformanceMode>
131
+ </ClCompile>
132
+ <Link>
133
+ <SubSystem>Console</SubSystem>
134
+ <GenerateDebugInformation>true</GenerateDebugInformation>
135
+ </Link>
136
+ </ItemDefinitionGroup>
137
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
138
+ <ClCompile>
139
+ <WarningLevel>Level3</WarningLevel>
140
+ <FunctionLevelLinking>true</FunctionLevelLinking>
141
+ <IntrinsicFunctions>true</IntrinsicFunctions>
142
+ <SDLCheck>true</SDLCheck>
143
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
144
+ <ConformanceMode>true</ConformanceMode>
145
+ </ClCompile>
146
+ <Link>
147
+ <SubSystem>Console</SubSystem>
148
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
149
+ <OptimizeReferences>true</OptimizeReferences>
150
+ <GenerateDebugInformation>true</GenerateDebugInformation>
151
+ </Link>
152
+ </ItemDefinitionGroup>
153
+ <ItemGroup>
154
+ <ClCompile Include="..\pycfutils\src\cinterface_win.cpp">
155
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
156
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
157
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
158
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
159
+ </ClCompile>
160
+ </ItemGroup>
161
+ <ItemGroup>
162
+ <ClInclude Include="..\pycfutils\include\pycfutils\cinterface.h" />
163
+ </ItemGroup>
164
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
165
+ <ImportGroup Label="ExtensionTargets">
166
+ </ImportGroup>
167
+ </Project>
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+ <ItemGroup>
4
+ <Filter Include="Source Files">
5
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
6
+ <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
7
+ </Filter>
8
+ <Filter Include="Header Files">
9
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10
+ <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
11
+ </Filter>
12
+ <Filter Include="Resource Files">
13
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
15
+ </Filter>
16
+ </ItemGroup>
17
+ <ItemGroup>
18
+ <ClCompile Include="..\pycfutils\src\cinterface_win.cpp">
19
+ <Filter>Source Files</Filter>
20
+ </ClCompile>
21
+ </ItemGroup>
22
+ <ItemGroup>
23
+ <ClInclude Include="..\pycfutils\include\pycfutils\cinterface.h">
24
+ <Filter>Header Files</Filter>
25
+ </ClInclude>
26
+ </ItemGroup>
27
+ </Project>