openjigware 0.1.0__py3-none-any.whl

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,284 @@
1
+ """
2
+ openjigware — OpenJigWare .NET 라이브러리의 Python 바인딩 (Windows/Linux/macOS 공용)
3
+
4
+ 사용법:
5
+ from openjigware import Ojw
6
+
7
+ dxl = Ojw.CProtocol2() # Dynamixel Protocol 2.0
8
+ dxl.Open(0, 1000000)
9
+
10
+ c3d = Ojw.C3d() # 3D / DH / IK
11
+
12
+ 필요 조건:
13
+ - pythonnet (pip 의존성으로 자동 설치)
14
+ - .NET 8+ CoreCLR 런타임. 없으면 관리자 권한 없이 사용자 폴더에 자동 설치(최초 1회, 인터넷 필요).
15
+ Windows: %LOCALAPPDATA%\\OpenJigWare\\dotnet
16
+ Linux/macOS: ~/.local/share/openjigware/dotnet
17
+ OJW_NO_BOOTSTRAP=1 이면 자동 설치를 끄고 안내 에러만 낸다.
18
+
19
+ 패키징 메모:
20
+ - OpenJigWare.dll 및 의존 어셈블리는 이 패키지의 _libs/ 에 동봉된다(pip 설치 시 함께 배포).
21
+ - pip 로 추출된 DLL 은 MOTW(Zone.Identifier) 가 없어 Windows SmartScreen 차단을 회피한다.
22
+ (Smart App Control '켜짐' 최강 모드만 코드 서명이 별도로 필요.)
23
+ - 이 파일의 로더 로직은 examples/shared/ojw.py 와 동일 계열이다(단, lib 경로는 _libs 고정).
24
+ """
25
+ import os
26
+ import sys
27
+ import platform
28
+
29
+ __version__ = "0.1.0"
30
+
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # .NET 런타임 탐색 / 부트스트랩
34
+ # ---------------------------------------------------------------------------
35
+ def _netcore_versions(root):
36
+ """<root>/shared/Microsoft.NETCore.App 아래 설치된 major 버전 목록."""
37
+ base = os.path.join(root, "shared", "Microsoft.NETCore.App")
38
+ majors = []
39
+ if os.path.isdir(base):
40
+ for name in os.listdir(base):
41
+ head = name.split(".", 1)[0]
42
+ if head.isdigit():
43
+ majors.append(int(head))
44
+ return majors
45
+
46
+
47
+ def _has_netcore8(root):
48
+ """root 가 유효한 dotnet 루트이고 Microsoft.NETCore.App 8+ 를 포함하는가."""
49
+ if not root or not os.path.isdir(root):
50
+ return False
51
+ return any(v >= 8 for v in _netcore_versions(root))
52
+
53
+
54
+ def _bootstrap_dir():
55
+ """자동 설치 대상 폴더 (사용자 권한)."""
56
+ if platform.system() == "Windows":
57
+ base = os.environ.get("LOCALAPPDATA") or os.path.expanduser("~")
58
+ return os.path.join(base, "OpenJigWare", "dotnet")
59
+ return os.path.expanduser("~/.local/share/openjigware/dotnet")
60
+
61
+
62
+ def _find_dotnet_root():
63
+ """DOTNET_ROOT → PATH → 기본 설치 경로 → 부트스트랩 폴더 순으로 .NET 8+ 탐색."""
64
+ import shutil
65
+
66
+ candidates = []
67
+
68
+ env_root = os.environ.get("DOTNET_ROOT")
69
+ if env_root:
70
+ candidates.append(env_root)
71
+
72
+ exe = shutil.which("dotnet")
73
+ if exe:
74
+ candidates.append(os.path.dirname(os.path.realpath(exe)))
75
+
76
+ if platform.system() == "Windows":
77
+ for var in ("ProgramFiles", "ProgramW6432", "ProgramFiles(x86)"):
78
+ pf = os.environ.get(var)
79
+ if pf:
80
+ candidates.append(os.path.join(pf, "dotnet"))
81
+ la = os.environ.get("LOCALAPPDATA")
82
+ if la:
83
+ candidates.append(os.path.join(la, "Microsoft", "dotnet"))
84
+ else:
85
+ candidates += [
86
+ "/usr/lib/dotnet", "/usr/share/dotnet", "/usr/local/share/dotnet",
87
+ os.path.expanduser("~/.dotnet"),
88
+ ]
89
+
90
+ candidates.append(_bootstrap_dir())
91
+
92
+ seen = set()
93
+ for root in candidates:
94
+ root = os.path.abspath(root)
95
+ if root in seen:
96
+ continue
97
+ seen.add(root)
98
+ if _has_netcore8(root):
99
+ return root
100
+ return None
101
+
102
+
103
+ def _bootstrap_dotnet():
104
+ """공식 dotnet-install 스크립트로 .NET 8 런타임을 사용자 폴더에 설치(관리자 불필요)."""
105
+ if os.environ.get("OJW_NO_BOOTSTRAP"):
106
+ return None
107
+
108
+ import subprocess
109
+ import tempfile
110
+ import urllib.request
111
+
112
+ install_dir = _bootstrap_dir()
113
+ is_win = platform.system() == "Windows"
114
+ url = "https://dot.net/v1/dotnet-install." + ("ps1" if is_win else "sh")
115
+
116
+ sys.stderr.write(
117
+ "[openjigware] .NET 8 런타임이 없어 사용자 폴더에 자동 설치합니다 (최초 1회, 인터넷 필요)\n"
118
+ "[openjigware] 설치 위치: {}\n".format(install_dir)
119
+ )
120
+ sys.stderr.flush()
121
+
122
+ try:
123
+ os.makedirs(install_dir, exist_ok=True)
124
+ suffix = ".ps1" if is_win else ".sh"
125
+ fd, script = tempfile.mkstemp(suffix=suffix, prefix="dotnet-install-")
126
+ os.close(fd)
127
+ urllib.request.urlretrieve(url, script)
128
+
129
+ if is_win:
130
+ cmd = [
131
+ "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass",
132
+ "-File", script,
133
+ "-Runtime", "dotnet", "-Channel", "8.0",
134
+ "-InstallDir", install_dir, "-NoPath",
135
+ ]
136
+ else:
137
+ os.chmod(script, 0o755)
138
+ cmd = [
139
+ "bash", script,
140
+ "--runtime", "dotnet", "--channel", "8.0",
141
+ "--install-dir", install_dir, "--no-path",
142
+ ]
143
+
144
+ rc = subprocess.call(cmd)
145
+ try:
146
+ os.remove(script)
147
+ except OSError:
148
+ pass
149
+
150
+ if rc == 0 and _has_netcore8(install_dir):
151
+ sys.stderr.write("[openjigware] .NET 8 런타임 설치 완료: {}\n".format(install_dir))
152
+ sys.stderr.flush()
153
+ return install_dir
154
+ sys.stderr.write("[openjigware] .NET 자동 설치 실패 (dotnet-install rc={})\n".format(rc))
155
+ except Exception as e: # noqa: BLE001 - 안내 목적, 세부 예외는 메시지로 노출
156
+ sys.stderr.write("[openjigware] .NET 자동 설치 중 오류: {}\n".format(e))
157
+ sys.stderr.flush()
158
+ return None
159
+
160
+
161
+ def _init_runtime():
162
+ """.NET 8 (CoreCLR) 초기화. 런타임을 찾거나 자동 설치한 뒤 pythonnet 을 CoreCLR 로 로드."""
163
+ try:
164
+ from pythonnet import load
165
+ except ImportError as e:
166
+ raise RuntimeError(
167
+ "pythonnet 이 필요합니다. 설치: pip install pythonnet\n"
168
+ " (원인: {})".format(e)
169
+ )
170
+
171
+ root = _find_dotnet_root()
172
+ if root is None:
173
+ root = _bootstrap_dotnet()
174
+
175
+ if root is None:
176
+ hint = ""
177
+ if os.environ.get("OJW_NO_BOOTSTRAP"):
178
+ hint = " OJW_NO_BOOTSTRAP 가 설정되어 자동 설치를 건너뛰었습니다.\n"
179
+ raise RuntimeError(
180
+ ".NET 8+ CoreCLR 런타임을 찾지 못했습니다.\n"
181
+ + hint +
182
+ " 수동 설치: https://dotnet.microsoft.com/download/dotnet/8.0 (Runtime)\n"
183
+ " 또는 DOTNET_ROOT 를 유효한 .NET 8 루트로 지정하세요."
184
+ )
185
+
186
+ os.environ["DOTNET_ROOT"] = root
187
+ os.environ["PATH"] = root + os.pathsep + os.environ.get("PATH", "")
188
+
189
+ try:
190
+ load("coreclr", dotnet_root=root)
191
+ except TypeError:
192
+ load("coreclr")
193
+
194
+
195
+ def _clear_motw(lib_dir):
196
+ """Windows MOTW(Zone.Identifier ADS) 해제 — 관리자 불필요. LoadFrom 차단 예방."""
197
+ if platform.system() != "Windows":
198
+ return
199
+ for base, _dirs, files in os.walk(lib_dir):
200
+ for name in files:
201
+ if name.lower().endswith((".dll", ".exe")):
202
+ try:
203
+ os.remove(os.path.join(base, name) + ":Zone.Identifier")
204
+ except OSError:
205
+ pass
206
+
207
+
208
+ def _find_lib_dir():
209
+ """동봉된 _libs 폴더(패키지 내부)를 우선, OJW_DLL 환경변수로 재정의 가능."""
210
+ env = os.environ.get("OJW_DLL")
211
+ if env and os.path.isfile(os.path.join(env, "OpenJigWare.dll")):
212
+ return os.path.abspath(env)
213
+ bundled = os.path.join(os.path.dirname(os.path.abspath(__file__)), "_libs")
214
+ if os.path.isfile(os.path.join(bundled, "OpenJigWare.dll")):
215
+ return bundled
216
+ return None
217
+
218
+
219
+ def _load_dll(lib_dir):
220
+ """OpenJigWare.dll + OS별 System.IO.Ports 실제 구현체 로드."""
221
+ import clr
222
+ sys.path.insert(0, lib_dir)
223
+
224
+ system = platform.system()
225
+
226
+ # pythonnet 3.x 는 clr.AddReference(fullpath) 를 assembly name 으로 오인하므로
227
+ # 파일 경로 로드는 Assembly.LoadFrom 을 직접 사용한다.
228
+ def _load_path(dll_path):
229
+ if not os.path.exists(dll_path):
230
+ return False
231
+ try:
232
+ from System.Reflection import Assembly
233
+ Assembly.LoadFrom(dll_path)
234
+ return True
235
+ except Exception as e:
236
+ print("[openjigware] warn: LoadFrom failed for {}: {}".format(dll_path, e))
237
+ return False
238
+
239
+ if system == "Windows":
240
+ _load_path(os.path.join(lib_dir, "runtimes", "win", "lib", "net8.0", "System.IO.Ports.dll"))
241
+ elif system in ("Linux", "Darwin"):
242
+ _load_path(os.path.join(lib_dir, "runtimes", "unix", "lib", "net8.0", "System.IO.Ports.dll"))
243
+
244
+ import ctypes
245
+ if system == "Linux":
246
+ arch = platform.machine().lower()
247
+ rids = ["linux-x64", "linux-arm64", "linux-arm"] if arch in ("x86_64", "amd64") else [f"linux-{arch}", "linux-arm64", "linux-arm"]
248
+ for rid in rids:
249
+ so = os.path.join(lib_dir, "runtimes", rid, "native", "libSystem.IO.Ports.Native.so")
250
+ if os.path.exists(so):
251
+ try:
252
+ ctypes.cdll.LoadLibrary(so)
253
+ break
254
+ except OSError:
255
+ pass
256
+ else: # Darwin
257
+ for rid in ["osx-x64", "osx-arm64"]:
258
+ dylib = os.path.join(lib_dir, "runtimes", rid, "native", "libSystem.IO.Ports.Native.dylib")
259
+ if os.path.exists(dylib):
260
+ try:
261
+ ctypes.cdll.LoadLibrary(dylib)
262
+ break
263
+ except OSError:
264
+ pass
265
+
266
+ if not _load_path(os.path.join(lib_dir, "OpenJigWare.dll")):
267
+ clr.AddReference("OpenJigWare")
268
+
269
+
270
+ # 초기화 (순서: lib 탐색 → MOTW 해제 → 런타임 → DLL 로드)
271
+ _lib_dir = _find_lib_dir()
272
+ if _lib_dir is None:
273
+ raise RuntimeError(
274
+ "OpenJigWare.dll 를 찾을 수 없습니다. 패키지가 손상됐거나 _libs 가 누락됐습니다.\n"
275
+ " 재설치: pip install --force-reinstall openjigware"
276
+ )
277
+
278
+ _clear_motw(_lib_dir)
279
+ _init_runtime()
280
+ _load_dll(_lib_dir)
281
+
282
+ from OpenJigWare import Ojw # noqa: E402
283
+
284
+ __all__ = ["Ojw", "__version__"]
@@ -0,0 +1,281 @@
1
+ {
2
+ "runtimeTarget": {
3
+ "name": ".NETCoreApp,Version=v8.0",
4
+ "signature": ""
5
+ },
6
+ "compilationOptions": {},
7
+ "targets": {
8
+ ".NETCoreApp,Version=v8.0": {
9
+ "OpenJigWare/1.0.0": {
10
+ "dependencies": {
11
+ "Microsoft.Win32.Registry": "5.0.0",
12
+ "System.Drawing.Common": "8.0.0",
13
+ "System.IO.Ports": "8.0.0",
14
+ "System.Management": "8.0.0"
15
+ },
16
+ "runtime": {
17
+ "OpenJigWare.dll": {}
18
+ }
19
+ },
20
+ "Microsoft.NETCore.Platforms/5.0.0": {},
21
+ "Microsoft.Win32.Registry/5.0.0": {
22
+ "dependencies": {
23
+ "System.Security.AccessControl": "5.0.0",
24
+ "System.Security.Principal.Windows": "5.0.0"
25
+ }
26
+ },
27
+ "Microsoft.Win32.SystemEvents/8.0.0": {
28
+ "runtime": {
29
+ "lib/net8.0/Microsoft.Win32.SystemEvents.dll": {
30
+ "assemblyVersion": "8.0.0.0",
31
+ "fileVersion": "8.0.23.53103"
32
+ }
33
+ },
34
+ "runtimeTargets": {
35
+ "runtimes/win/lib/net8.0/Microsoft.Win32.SystemEvents.dll": {
36
+ "rid": "win",
37
+ "assetType": "runtime",
38
+ "assemblyVersion": "8.0.0.0",
39
+ "fileVersion": "8.0.23.53103"
40
+ }
41
+ }
42
+ },
43
+ "runtime.linux-arm.runtime.native.System.IO.Ports/8.0.0": {
44
+ "runtimeTargets": {
45
+ "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": {
46
+ "rid": "linux-arm",
47
+ "assetType": "native",
48
+ "fileVersion": "0.0.0.0"
49
+ }
50
+ }
51
+ },
52
+ "runtime.linux-arm64.runtime.native.System.IO.Ports/8.0.0": {
53
+ "runtimeTargets": {
54
+ "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": {
55
+ "rid": "linux-arm64",
56
+ "assetType": "native",
57
+ "fileVersion": "0.0.0.0"
58
+ }
59
+ }
60
+ },
61
+ "runtime.linux-x64.runtime.native.System.IO.Ports/8.0.0": {
62
+ "runtimeTargets": {
63
+ "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": {
64
+ "rid": "linux-x64",
65
+ "assetType": "native",
66
+ "fileVersion": "0.0.0.0"
67
+ }
68
+ }
69
+ },
70
+ "runtime.native.System.IO.Ports/8.0.0": {
71
+ "dependencies": {
72
+ "runtime.linux-arm.runtime.native.System.IO.Ports": "8.0.0",
73
+ "runtime.linux-arm64.runtime.native.System.IO.Ports": "8.0.0",
74
+ "runtime.linux-x64.runtime.native.System.IO.Ports": "8.0.0",
75
+ "runtime.osx-arm64.runtime.native.System.IO.Ports": "8.0.0",
76
+ "runtime.osx-x64.runtime.native.System.IO.Ports": "8.0.0"
77
+ }
78
+ },
79
+ "runtime.osx-arm64.runtime.native.System.IO.Ports/8.0.0": {
80
+ "runtimeTargets": {
81
+ "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": {
82
+ "rid": "osx-arm64",
83
+ "assetType": "native",
84
+ "fileVersion": "0.0.0.0"
85
+ }
86
+ }
87
+ },
88
+ "runtime.osx-x64.runtime.native.System.IO.Ports/8.0.0": {
89
+ "runtimeTargets": {
90
+ "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": {
91
+ "rid": "osx-x64",
92
+ "assetType": "native",
93
+ "fileVersion": "0.0.0.0"
94
+ }
95
+ }
96
+ },
97
+ "System.CodeDom/8.0.0": {
98
+ "runtime": {
99
+ "lib/net8.0/System.CodeDom.dll": {
100
+ "assemblyVersion": "8.0.0.0",
101
+ "fileVersion": "8.0.23.53103"
102
+ }
103
+ }
104
+ },
105
+ "System.Drawing.Common/8.0.0": {
106
+ "dependencies": {
107
+ "Microsoft.Win32.SystemEvents": "8.0.0"
108
+ },
109
+ "runtime": {
110
+ "lib/net8.0/System.Drawing.Common.dll": {
111
+ "assemblyVersion": "8.0.0.0",
112
+ "fileVersion": "8.0.23.53105"
113
+ }
114
+ }
115
+ },
116
+ "System.IO.Ports/8.0.0": {
117
+ "dependencies": {
118
+ "runtime.native.System.IO.Ports": "8.0.0"
119
+ },
120
+ "runtime": {
121
+ "lib/net8.0/System.IO.Ports.dll": {
122
+ "assemblyVersion": "8.0.0.0",
123
+ "fileVersion": "8.0.23.53103"
124
+ }
125
+ },
126
+ "runtimeTargets": {
127
+ "runtimes/unix/lib/net8.0/System.IO.Ports.dll": {
128
+ "rid": "unix",
129
+ "assetType": "runtime",
130
+ "assemblyVersion": "8.0.0.0",
131
+ "fileVersion": "8.0.23.53103"
132
+ },
133
+ "runtimes/win/lib/net8.0/System.IO.Ports.dll": {
134
+ "rid": "win",
135
+ "assetType": "runtime",
136
+ "assemblyVersion": "8.0.0.0",
137
+ "fileVersion": "8.0.23.53103"
138
+ }
139
+ }
140
+ },
141
+ "System.Management/8.0.0": {
142
+ "dependencies": {
143
+ "System.CodeDom": "8.0.0"
144
+ },
145
+ "runtime": {
146
+ "lib/net8.0/System.Management.dll": {
147
+ "assemblyVersion": "8.0.0.0",
148
+ "fileVersion": "8.0.23.53103"
149
+ }
150
+ },
151
+ "runtimeTargets": {
152
+ "runtimes/win/lib/net8.0/System.Management.dll": {
153
+ "rid": "win",
154
+ "assetType": "runtime",
155
+ "assemblyVersion": "8.0.0.0",
156
+ "fileVersion": "8.0.23.53103"
157
+ }
158
+ }
159
+ },
160
+ "System.Security.AccessControl/5.0.0": {
161
+ "dependencies": {
162
+ "Microsoft.NETCore.Platforms": "5.0.0",
163
+ "System.Security.Principal.Windows": "5.0.0"
164
+ }
165
+ },
166
+ "System.Security.Principal.Windows/5.0.0": {}
167
+ }
168
+ },
169
+ "libraries": {
170
+ "OpenJigWare/1.0.0": {
171
+ "type": "project",
172
+ "serviceable": false,
173
+ "sha512": ""
174
+ },
175
+ "Microsoft.NETCore.Platforms/5.0.0": {
176
+ "type": "package",
177
+ "serviceable": true,
178
+ "sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
179
+ "path": "microsoft.netcore.platforms/5.0.0",
180
+ "hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
181
+ },
182
+ "Microsoft.Win32.Registry/5.0.0": {
183
+ "type": "package",
184
+ "serviceable": true,
185
+ "sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
186
+ "path": "microsoft.win32.registry/5.0.0",
187
+ "hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512"
188
+ },
189
+ "Microsoft.Win32.SystemEvents/8.0.0": {
190
+ "type": "package",
191
+ "serviceable": true,
192
+ "sha512": "sha512-9opKRyOKMCi2xJ7Bj7kxtZ1r9vbzosMvRrdEhVhDz8j8MoBGgB+WmC94yH839NPH+BclAjtQ/pyagvi/8gDLkw==",
193
+ "path": "microsoft.win32.systemevents/8.0.0",
194
+ "hashPath": "microsoft.win32.systemevents.8.0.0.nupkg.sha512"
195
+ },
196
+ "runtime.linux-arm.runtime.native.System.IO.Ports/8.0.0": {
197
+ "type": "package",
198
+ "serviceable": true,
199
+ "sha512": "sha512-gK720fg6HemDg8sXcfy+xCMZ9+hF78Gc7BmREbmkS4noqlu1BAr9qZtuWGhLzFjBfgecmdtl4+SYVwJ1VneZBQ==",
200
+ "path": "runtime.linux-arm.runtime.native.system.io.ports/8.0.0",
201
+ "hashPath": "runtime.linux-arm.runtime.native.system.io.ports.8.0.0.nupkg.sha512"
202
+ },
203
+ "runtime.linux-arm64.runtime.native.System.IO.Ports/8.0.0": {
204
+ "type": "package",
205
+ "serviceable": true,
206
+ "sha512": "sha512-KYG6/3ojhEWbb3FwQAKgGWPHrY+HKUXXdVjJlrtyCLn3EMcNTaNcPadb2c0ndQzixZSmAxZKopXJr0nLwhOrpQ==",
207
+ "path": "runtime.linux-arm64.runtime.native.system.io.ports/8.0.0",
208
+ "hashPath": "runtime.linux-arm64.runtime.native.system.io.ports.8.0.0.nupkg.sha512"
209
+ },
210
+ "runtime.linux-x64.runtime.native.System.IO.Ports/8.0.0": {
211
+ "type": "package",
212
+ "serviceable": true,
213
+ "sha512": "sha512-Wnw5vhA4mgGbIFoo6l9Fk3iEcwRSq49a1aKwJgXUCUtEQLCSUDjTGSxqy/oMUuOyyn7uLHsH8KgZzQ1y3lReiQ==",
214
+ "path": "runtime.linux-x64.runtime.native.system.io.ports/8.0.0",
215
+ "hashPath": "runtime.linux-x64.runtime.native.system.io.ports.8.0.0.nupkg.sha512"
216
+ },
217
+ "runtime.native.System.IO.Ports/8.0.0": {
218
+ "type": "package",
219
+ "serviceable": true,
220
+ "sha512": "sha512-Ee7Sz5llLpTgyKIWzKI/GeuRSbFkOABgJRY00SqTY0OkTYtkB+9l5rFZfE7fxPA3c22RfytCBYkUdAkcmwMjQg==",
221
+ "path": "runtime.native.system.io.ports/8.0.0",
222
+ "hashPath": "runtime.native.system.io.ports.8.0.0.nupkg.sha512"
223
+ },
224
+ "runtime.osx-arm64.runtime.native.System.IO.Ports/8.0.0": {
225
+ "type": "package",
226
+ "serviceable": true,
227
+ "sha512": "sha512-rbUBLAaFW9oVkbsb0+XSrAo2QdhBeAyzLl5KQ6Oci9L/u626uXGKInsVJG6B9Z5EO8bmplC8tsMiaHK8wOBZ+w==",
228
+ "path": "runtime.osx-arm64.runtime.native.system.io.ports/8.0.0",
229
+ "hashPath": "runtime.osx-arm64.runtime.native.system.io.ports.8.0.0.nupkg.sha512"
230
+ },
231
+ "runtime.osx-x64.runtime.native.System.IO.Ports/8.0.0": {
232
+ "type": "package",
233
+ "serviceable": true,
234
+ "sha512": "sha512-IcfB4jKtM9pkzP9OpYelEcUX1MiDt0IJPBh3XYYdEISFF+6Mc+T8WWi0dr9wVh1gtcdVjubVEIBgB8BHESlGfQ==",
235
+ "path": "runtime.osx-x64.runtime.native.system.io.ports/8.0.0",
236
+ "hashPath": "runtime.osx-x64.runtime.native.system.io.ports.8.0.0.nupkg.sha512"
237
+ },
238
+ "System.CodeDom/8.0.0": {
239
+ "type": "package",
240
+ "serviceable": true,
241
+ "sha512": "sha512-WTlRjL6KWIMr/pAaq3rYqh0TJlzpouaQ/W1eelssHgtlwHAH25jXTkUphTYx9HaIIf7XA6qs/0+YhtLEQRkJ+Q==",
242
+ "path": "system.codedom/8.0.0",
243
+ "hashPath": "system.codedom.8.0.0.nupkg.sha512"
244
+ },
245
+ "System.Drawing.Common/8.0.0": {
246
+ "type": "package",
247
+ "serviceable": true,
248
+ "sha512": "sha512-JkbHJjtI/dWc5dfmEdJlbe3VwgZqCkZRtfuWFh5GOv0f+gGCfBtzMpIVkmdkj2AObO9y+oiOi81UGwH3aBYuqA==",
249
+ "path": "system.drawing.common/8.0.0",
250
+ "hashPath": "system.drawing.common.8.0.0.nupkg.sha512"
251
+ },
252
+ "System.IO.Ports/8.0.0": {
253
+ "type": "package",
254
+ "serviceable": true,
255
+ "sha512": "sha512-MaiPbx2/QXZc62gm/DrajRrGPG1lU4m08GWMoWiymPYM+ba4kfACp2PbiYpqJ4QiFGhHD00zX3RoVDTucjWe9g==",
256
+ "path": "system.io.ports/8.0.0",
257
+ "hashPath": "system.io.ports.8.0.0.nupkg.sha512"
258
+ },
259
+ "System.Management/8.0.0": {
260
+ "type": "package",
261
+ "serviceable": true,
262
+ "sha512": "sha512-jrK22i5LRzxZCfGb+tGmke2VH7oE0DvcDlJ1HAKYU8cPmD8XnpUT0bYn2Gy98GEhGjtfbR/sxKTVb+dE770pfA==",
263
+ "path": "system.management/8.0.0",
264
+ "hashPath": "system.management.8.0.0.nupkg.sha512"
265
+ },
266
+ "System.Security.AccessControl/5.0.0": {
267
+ "type": "package",
268
+ "serviceable": true,
269
+ "sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
270
+ "path": "system.security.accesscontrol/5.0.0",
271
+ "hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512"
272
+ },
273
+ "System.Security.Principal.Windows/5.0.0": {
274
+ "type": "package",
275
+ "serviceable": true,
276
+ "sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==",
277
+ "path": "system.security.principal.windows/5.0.0",
278
+ "hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
279
+ }
280
+ }
281
+ }
Binary file
Binary file
Binary file
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: openjigware
3
+ Version: 0.1.0
4
+ Summary: Python bindings for the OpenJigWare .NET robotics library (Dynamixel protocols, forward/inverse kinematics, DH/URDF, 3D)
5
+ Author: OpenJigWare
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/oroca/OpenJigWare
8
+ Project-URL: Source, https://github.com/oroca/OpenJigWare
9
+ Keywords: robotics,dynamixel,kinematics,inverse-kinematics,urdf,dh,openjigware,pythonnet,dotnet
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: Microsoft :: Windows
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: C#
24
+ Classifier: Topic :: Scientific/Engineering
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: pythonnet>=3.0.3
30
+ Dynamic: license-file
31
+
32
+ # OpenJigWare (Python)
33
+
34
+ Python bindings for the **OpenJigWare** .NET robotics library — Dynamixel
35
+ protocols, forward/inverse kinematics, DH parameters, URDF/MJCF/USD export,
36
+ and a browser-based 3D viewer. Runs on **Windows, Linux, and macOS**.
37
+
38
+ ```bash
39
+ pip install openjigware
40
+ ```
41
+
42
+ ```python
43
+ from openjigware import Ojw
44
+
45
+ # Dynamixel Protocol 2.0
46
+ dxl = Ojw.CProtocol2()
47
+ dxl.Open(0, 1000000)
48
+
49
+ # 3D / DH / inverse kinematics
50
+ c3d = Ojw.C3d()
51
+ ```
52
+
53
+ ## How it works
54
+
55
+ `openjigware` ships the compiled `OpenJigWare.dll` (a cross-platform .NET 8
56
+ assembly) inside the wheel and loads it through
57
+ [pythonnet](https://pypi.org/project/pythonnet/).
58
+
59
+ - **pythonnet** is installed automatically as a dependency.
60
+ - **.NET 8 runtime**: if a suitable CoreCLR runtime is not found, it is
61
+ installed automatically into a user folder — no admin rights required
62
+ (first run only, needs internet):
63
+ - Windows: `%LOCALAPPDATA%\OpenJigWare\dotnet`
64
+ - Linux/macOS: `~/.local/share/openjigware/dotnet`
65
+
66
+ Set `OJW_NO_BOOTSTRAP=1` to disable auto-install (a clear error is raised
67
+ instead). Point `DOTNET_ROOT` at an existing .NET 8 root to use your own.
68
+
69
+ ## Windows security note
70
+
71
+ Because pip extracts the bundled DLLs locally, they carry **no Mark-of-the-Web
72
+ (Zone.Identifier)** tag — so the SmartScreen "blocked / unknown publisher"
73
+ failures that plague manually-copied DLLs do not occur. Windows 11 **Smart App
74
+ Control** in its strictest enforced mode may still require Authenticode code
75
+ signing, which is outside the scope of pip.
76
+
77
+ ## Requirements
78
+
79
+ - Python 3.8+
80
+ - pythonnet 3.0.3+ (installed automatically)
81
+ - .NET 8+ runtime (installed automatically if missing)
82
+
83
+ ## License
84
+
85
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,21 @@
1
+ openjigware/__init__.py,sha256=X7aMF4JdTQ_jqyCGzhWSQurV0eg7BYJxEIwVeFCf7-M,10245
2
+ openjigware/_libs/Microsoft.Win32.SystemEvents.dll,sha256=0n7MnfN5N66bcDaS8Jl1c3J6tE_4mJuRwK2_MolKXls,25880
3
+ openjigware/_libs/OpenJigWare.deps.json,sha256=_BaKLpl6egizOptKLRgMDDPIAwtyvpil0vpLIzNgev0,10938
4
+ openjigware/_libs/OpenJigWare.dll,sha256=2KiP5_pnLiJxk1cvQXZj9WLPtCGYrMtChkglmAgm-H8,2555904
5
+ openjigware/_libs/System.Drawing.Common.dll,sha256=kDPOh9IwfLwQKyPkCW5h5QTc4OtOVv8EW9d5xufQwJQ,610992
6
+ openjigware/_libs/System.IO.Ports.dll,sha256=fYOXYDz6iwdgMcSdOyiujZAI58L1wFvM1ce60uyScGU,35488
7
+ openjigware/_libs/System.Management.dll,sha256=xfaaJY_GCdQubVCQPptESQJ_TTMvqo2uwEvcPLkobUs,72968
8
+ openjigware/_libs/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so,sha256=oE_Bmvawk0mp3Ap7Sz6_Qc43J1EP5bfcltz7v2PjqMw,9568
9
+ openjigware/_libs/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so,sha256=MOsL5bFyepCMtfQwof0jxE8TrIvOuFIzRWM3Cr7o-rY,14632
10
+ openjigware/_libs/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so,sha256=LSIRSmrTq6yd9CElSFYc-CngVjwUJcb2aaN50aYdXwY,14488
11
+ openjigware/_libs/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib,sha256=K-TA7BH2qtVZHBuE8qADl2qIsNh1YuMbQGuhpyyoCP8,70464
12
+ openjigware/_libs/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib,sha256=McXVu3xhKhe03QH6Ytuo8hAe_eAWwShZfm_7W4_6ayA,70480
13
+ openjigware/_libs/runtimes/unix/lib/net8.0/System.IO.Ports.dll,sha256=KooUlKyK_dZwuWZ0q_LXGvQXdBQwGkJllbqWmdVDpxg,74416
14
+ openjigware/_libs/runtimes/win/lib/net8.0/Microsoft.Win32.SystemEvents.dll,sha256=szJ806caTMKiRqpb02wjxzjYjxck0OovT1UGI8na9V4,58632
15
+ openjigware/_libs/runtimes/win/lib/net8.0/System.IO.Ports.dll,sha256=jWybK__gF0HRtJFf4myTuowjgrAO5M-IoxKniWGe9QM,87728
16
+ openjigware/_libs/runtimes/win/lib/net8.0/System.Management.dll,sha256=stbn6ZHcnvFUsp9JZvBP2O1OuywdEkLqHV8-kPiuUUM,311984
17
+ openjigware-0.1.0.dist-info/licenses/LICENSE,sha256=IWCAPReZG-swozP6L0U0ZZS6fYxnRa3tXHa5tg_XkOg,1068
18
+ openjigware-0.1.0.dist-info/METADATA,sha256=J5u11i7QpNwqXWNbeSUp6NH3ism3cw415hVHueFXN1Y,3134
19
+ openjigware-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
20
+ openjigware-0.1.0.dist-info/top_level.txt,sha256=DAQ76QSYMqsL1_UBWEguXqCbax9JumUj--PGPNzmxlQ,12
21
+ openjigware-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenJigWare
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 @@
1
+ openjigware