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.
- pycfutils-2024.5.8/LICENSE +21 -0
- pycfutils-2024.5.8/PKG-INFO +56 -0
- pycfutils-2024.5.8/README.md +30 -0
- pycfutils-2024.5.8/pycfutils/__init__.py +1 -0
- pycfutils-2024.5.8/pycfutils/common.py +64 -0
- pycfutils-2024.5.8/pycfutils/ctypes.py +119 -0
- pycfutils-2024.5.8/pycfutils/gui/__init__.py +66 -0
- pycfutils-2024.5.8/pycfutils/gui/constants.py +81 -0
- pycfutils-2024.5.8/pycfutils/include/pycfutils/cinterface.h +38 -0
- pycfutils-2024.5.8/pycfutils/keyboard.py +94 -0
- pycfutils-2024.5.8/pycfutils/src/cinterface_win.cpp +122 -0
- pycfutils-2024.5.8/pycfutils/tests/__init__.py +1 -0
- pycfutils-2024.5.8/pycfutils/tests/test_common.py +57 -0
- pycfutils-2024.5.8/pycfutils/tests/test_ctypes.py +34 -0
- pycfutils-2024.5.8/pycfutils/tests/test_gui.py +14 -0
- pycfutils-2024.5.8/pycfutils/tests/test_keyboard.py +14 -0
- pycfutils-2024.5.8/pycfutils.egg-info/PKG-INFO +56 -0
- pycfutils-2024.5.8/pycfutils.egg-info/SOURCES.txt +23 -0
- pycfutils-2024.5.8/pycfutils.egg-info/dependency_links.txt +1 -0
- pycfutils-2024.5.8/pycfutils.egg-info/top_level.txt +1 -0
- pycfutils-2024.5.8/setup.cfg +4 -0
- pycfutils-2024.5.8/setup.py +161 -0
- pycfutils-2024.5.8/vs/vs.sln +31 -0
- pycfutils-2024.5.8/vs/vs.vcxproj +167 -0
- pycfutils-2024.5.8/vs/vs.vcxproj.filters +27 -0
|
@@ -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
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pycfutils
|
|
@@ -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>
|