pmxt 1.4.0__py3-none-any.whl → 1.4.1__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.
pmxt/__init__.py CHANGED
@@ -33,7 +33,7 @@ from .models import (
33
33
  CreateOrderParams,
34
34
  )
35
35
 
36
- __version__ = "1.4.0"
36
+ __version__ = "1.4.1"
37
37
  __all__ = [
38
38
  # Exchanges
39
39
  "Polymarket",
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PMXT Server Launcher
5
+ *
6
+ * This script ensures the PMXT sidecar server is running.
7
+ * It's designed to be called by SDKs in any language (Python, Java, C#, Go, etc.)
8
+ *
9
+ * Behavior:
10
+ * 1. Check if server is already running (via lock file)
11
+ * 2. If running, exit successfully
12
+ * 3. If not running, spawn the server and wait for health check
13
+ * 4. Exit with code 0 on success, 1 on failure
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const os = require('os');
19
+ const { spawn } = require('child_process');
20
+ const http = require('http');
21
+
22
+ const LOCK_FILE = path.join(os.homedir(), '.pmxt', 'server.lock');
23
+ const DEFAULT_PORT = 3847;
24
+ const HEALTH_CHECK_TIMEOUT = 10000; // 10 seconds
25
+ const HEALTH_CHECK_INTERVAL = 100; // 100ms
26
+
27
+ /**
28
+ * Check if the server is currently running
29
+ */
30
+ function isServerRunning() {
31
+ try {
32
+ if (!fs.existsSync(LOCK_FILE)) {
33
+ return false;
34
+ }
35
+
36
+ const lockData = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf-8'));
37
+ const { pid, port } = lockData;
38
+
39
+ // Check if process exists
40
+ try {
41
+ process.kill(pid, 0); // Signal 0 checks existence without killing
42
+ return { running: true, port };
43
+ } catch (err) {
44
+ // Process doesn't exist, remove stale lock file
45
+ fs.unlinkSync(LOCK_FILE);
46
+ return false;
47
+ }
48
+ } catch (err) {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Wait for server to respond to health check
55
+ */
56
+ function waitForHealth(port, timeout = HEALTH_CHECK_TIMEOUT) {
57
+ return new Promise((resolve, reject) => {
58
+ const startTime = Date.now();
59
+
60
+ const checkHealth = () => {
61
+ const req = http.get(`http://localhost:${port}/health`, (res) => {
62
+ if (res.statusCode === 200) {
63
+ resolve(true);
64
+ } else {
65
+ scheduleNextCheck();
66
+ }
67
+ });
68
+
69
+ req.on('error', () => {
70
+ scheduleNextCheck();
71
+ });
72
+
73
+ req.setTimeout(1000);
74
+ };
75
+
76
+ const scheduleNextCheck = () => {
77
+ if (Date.now() - startTime > timeout) {
78
+ reject(new Error('Server health check timeout'));
79
+ } else {
80
+ setTimeout(checkHealth, HEALTH_CHECK_INTERVAL);
81
+ }
82
+ };
83
+
84
+ checkHealth();
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Start the PMXT server
90
+ */
91
+ async function startServer() {
92
+ // 1. Try to find the server binary/script
93
+ let serverCmd = 'pmxt-server';
94
+ let args = [];
95
+
96
+ // Check for Python-bundled server (when bundled in pip package)
97
+ const pythonBundledServer = path.join(__dirname, '..', 'server', 'bundled.js');
98
+ // Check for local dev bundled server
99
+ const localBundledServer = path.join(__dirname, '..', 'dist', 'server', 'bundled.js');
100
+ const localDistServer = path.join(__dirname, '..', 'dist', 'server', 'index.js');
101
+ const localBinServer = path.join(__dirname, 'pmxt-server');
102
+
103
+ if (fs.existsSync(pythonBundledServer)) {
104
+ serverCmd = 'node';
105
+ args = [pythonBundledServer];
106
+ } else if (fs.existsSync(localBundledServer)) {
107
+ serverCmd = 'node';
108
+ args = [localBundledServer];
109
+ } else if (fs.existsSync(localDistServer)) {
110
+ serverCmd = 'node';
111
+ args = [localDistServer];
112
+ } else if (fs.existsSync(localBinServer)) {
113
+ serverCmd = localBinServer;
114
+ }
115
+
116
+ // Spawn server as detached process
117
+ const serverProcess = spawn(serverCmd, args, {
118
+ detached: true,
119
+ stdio: 'ignore',
120
+ env: process.env
121
+ });
122
+
123
+ // Detach from parent process
124
+ serverProcess.unref();
125
+
126
+ // Wait for server to be ready
127
+ await waitForHealth(DEFAULT_PORT);
128
+ }
129
+
130
+ /**
131
+ * Main entry point
132
+ */
133
+ async function main() {
134
+ try {
135
+ // Check if server is already running
136
+ const serverStatus = isServerRunning();
137
+
138
+ if (serverStatus && serverStatus.running) {
139
+ // Server is running, verify it's healthy
140
+ try {
141
+ await waitForHealth(serverStatus.port, 2000);
142
+ process.exit(0);
143
+ } catch (err) {
144
+ // Server process exists but not responding, try to start fresh
145
+ console.error('Server process exists but not responding, starting fresh...');
146
+ }
147
+ }
148
+
149
+ // Start the server
150
+ await startServer();
151
+ process.exit(0);
152
+ } catch (err) {
153
+ console.error('Failed to ensure server is running:', err.message);
154
+ process.exit(1);
155
+ }
156
+ }
157
+
158
+ main();
pmxt/server_manager.py CHANGED
@@ -209,15 +209,19 @@ class ServerManager:
209
209
  Start the server using the pmxt-ensure-server launcher.
210
210
  """
211
211
  # 1. Check for bundled server (PRODUCTION - installed via pip)
212
- bundled_launcher = Path(__file__).parent / '_server' / 'bin' / 'pmxt-ensure-server'
213
-
212
+ launcher_filename = 'pmxt-ensure-server'
213
+ if os.name == "nt": # Check if running Windows
214
+ launcher_filename += ".js"
215
+
216
+ bundled_launcher = Path(__file__).parent / '_server' / 'bin' / launcher_filename
217
+
214
218
  # 2. Check for monorepo structure (DEVELOPMENT)
215
219
  current_file = Path(__file__).resolve()
216
- local_launcher = current_file.parent.parent.parent.parent / 'core' / 'bin' / 'pmxt-ensure-server'
217
-
220
+ local_launcher = current_file.parent.parent.parent.parent / 'core' / 'bin' / launcher_filename
221
+
218
222
  # 3. Check PATH (GLOBAL INSTALL)
219
- path_launcher = shutil.which('pmxt-ensure-server')
220
-
223
+ path_launcher = shutil.which(launcher_filename)
224
+
221
225
  # Priority order: bundled > local dev > PATH
222
226
  if bundled_launcher.exists():
223
227
  launcher = str(bundled_launcher)
@@ -235,7 +239,7 @@ class ServerManager:
235
239
 
236
240
  # Call the launcher
237
241
  try:
238
- # If it's a JS file and we are calling it directly, might need node
242
+ # If it's a JS file, and we are calling it directly, might need node
239
243
  cmd = [launcher]
240
244
  if launcher.endswith('.js') or not os.access(launcher, os.X_OK):
241
245
  cmd = ['node', launcher]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pmxt
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: Unified prediction market data API - The ccxt for prediction markets
5
5
  Author: PMXT Contributors
6
6
  License: MIT
@@ -1,14 +1,15 @@
1
- pmxt/__init__.py,sha256=MAOqnWgwuaG-IN2JEPoGdUrp2DHARbZAFjHd-SmyEvs,1150
1
+ pmxt/__init__.py,sha256=MF02BpWSi_lMTTekzj6fxuZn9EBApLDlxqG9XfyHURs,1150
2
2
  pmxt/client.py,sha256=1qa8ObZtf-tdzhDXQXvWWdeLvGbyxsiVHAgQvl8Z4Uk,32955
3
3
  pmxt/models.py,sha256=-jiQ9mmv_qnF6mzj3DrvNgEA77tE_Pl0RCblM1VbV7o,8581
4
- pmxt/server_manager.py,sha256=-G97dYEdKl7F3HK9bAOKYl-SGWP6HsvzZIx2QxiZm24,11494
4
+ pmxt/server_manager.py,sha256=6uS1LIZ2d5d_K-MtbMUAlCZvbvhZ_iyofKok55HEofc,11606
5
5
  pmxt/_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  pmxt/_server/bin/pmxt-ensure-server,sha256=kXIond0UbxS52FAVQD7kHmSBaL_s6cbIyapLRr4KZJw,4544
7
+ pmxt/_server/bin/pmxt-ensure-server.js,sha256=kXIond0UbxS52FAVQD7kHmSBaL_s6cbIyapLRr4KZJw,4544
7
8
  pmxt/_server/server/bundled.js,sha256=ETpsJ6ZmRtO1gQmBZYwwHWTHJIEI8ooeeMhOwoeDJ84,4198184
8
- pmxt_internal/__init__.py,sha256=Kbxeq4WFfhIjcDkz72ZeXhWFpecUcOXCwUgqUzs6qsw,7578
9
- pmxt_internal/api_client.py,sha256=2XZZdrKh90kAA4P3bJ54IdzRfAFMawSUqwnp2pRZNYA,27889
9
+ pmxt_internal/__init__.py,sha256=Uxuh0MqjsHQ7vIaFnF5ZFSVlu4uJJFRDkQ_ued-QLHc,7578
10
+ pmxt_internal/api_client.py,sha256=0IalYtBszV5nLMHLkPqwECHqeWVOdE6ROcPrH72zwHs,27889
10
11
  pmxt_internal/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
11
- pmxt_internal/configuration.py,sha256=evyyjQzPpYofXsIUdNKTMlMbpmq38l2ISokDuXJ0qJ0,18320
12
+ pmxt_internal/configuration.py,sha256=uo3MWYp8NBZ8lVhNrWRWWSDzSOfuYF0O5RLuV4FUUUs,18320
12
13
  pmxt_internal/exceptions.py,sha256=txF8A7vlan57JS69kFPs-IZF-Qhp7IZobBTJVa4fOaM,6644
13
14
  pmxt_internal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
15
  pmxt_internal/rest.py,sha256=FMj4yaV6XLr842u_ScWHSzQsTFdk0jaUeuWLJoRbogQ,9760
@@ -64,7 +65,7 @@ pmxt_internal/models/unified_market.py,sha256=DoYhiH4HycYGlq858PEeB-CIA7haT6rxmJ
64
65
  pmxt_internal/models/watch_order_book_request.py,sha256=kavGUI-SLz2-Kam_jcJ_h0GDe0-9UkxqCmVsAi6Uios,3726
65
66
  pmxt_internal/models/watch_order_book_request_args_inner.py,sha256=ZHrjmFDGxRG5MXbuz4mUp9KFfo3XS7zuXWTyMNgi4xI,5464
66
67
  pmxt_internal/models/watch_trades_request.py,sha256=brrg8JbEe-aeg7mIe_Y2HzRPogp-IfRhkXChrxzqoLU,3722
67
- pmxt-1.4.0.dist-info/METADATA,sha256=6fTb2tiWCkPoyKkYSs16e6yzhUdp-s-NaE7NPY6VFhc,6449
68
- pmxt-1.4.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
69
- pmxt-1.4.0.dist-info/top_level.txt,sha256=J_jrcouJ-x-5lpcXMxeW0GOSi1HsBVR5_PdSfvigVrw,19
70
- pmxt-1.4.0.dist-info/RECORD,,
68
+ pmxt-1.4.1.dist-info/METADATA,sha256=3y8vXwX2n2sDBosp4CCbL3YN7SVpsV7yVF2CHp5B5fw,6449
69
+ pmxt-1.4.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
70
+ pmxt-1.4.1.dist-info/top_level.txt,sha256=J_jrcouJ-x-5lpcXMxeW0GOSi1HsBVR5_PdSfvigVrw,19
71
+ pmxt-1.4.1.dist-info/RECORD,,
pmxt_internal/__init__.py CHANGED
@@ -14,7 +14,7 @@
14
14
  """ # noqa: E501
15
15
 
16
16
 
17
- __version__ = "1.4.0"
17
+ __version__ = "1.4.1"
18
18
 
19
19
  # Define package exports
20
20
  __all__ = [
@@ -91,7 +91,7 @@ class ApiClient:
91
91
  self.default_headers[header_name] = header_value
92
92
  self.cookie = cookie
93
93
  # Set default User-Agent.
94
- self.user_agent = 'OpenAPI-Generator/1.4.0/python'
94
+ self.user_agent = 'OpenAPI-Generator/1.4.1/python'
95
95
  self.client_side_validation = configuration.client_side_validation
96
96
 
97
97
  def __enter__(self):
@@ -506,7 +506,7 @@ class Configuration:
506
506
  "OS: {env}\n"\
507
507
  "Python Version: {pyversion}\n"\
508
508
  "Version of the API: 0.4.4\n"\
509
- "SDK Package Version: 1.4.0".\
509
+ "SDK Package Version: 1.4.1".\
510
510
  format(env=sys.platform, pyversion=sys.version)
511
511
 
512
512
  def get_host_settings(self) -> List[HostSetting]:
File without changes