Skip to content

Commit b905958

Browse files
committed
Add trial_callback to the example, and the callback parameter to the ta.use_trial() function.
Code improvements. Remove some dead code.
1 parent c7a20e1 commit b905958

File tree

5 files changed

+70
-16
lines changed

5 files changed

+70
-16
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to this project are documented in this file.
44

5+
## 4.4.4.1 - 2021-05-27
6+
7+
* Add `trial_callback` to the example, and the callback parameter to the ta.use_trial() function.
8+
* Code improvements. Remove some dead code.
9+
510
## 4.4.4 - 2021-05-06
611

712
* Remove unused "sandbox" flag and error code. Sandboxes are VMs.

example.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
TurboActivateError,
99
TurboActivateTrialExpiredError,
1010
TA_USER,
11-
TA_SYSTEM
11+
TA_SYSTEM,
12+
TA_CB_EXPIRED,
13+
TA_CB_EXPIRED_FRAUD
1214
)
1315

1416
import sys
@@ -20,6 +22,29 @@
2022
DAYS_BETWEEN_CHECKS = 90
2123
GRACE_PERIOD_LENGTH = 14
2224

25+
'''
26+
This function will be called by a separate background thread to notify
27+
your app of trial expiration (either naturally, or because of customer fraud).
28+
29+
That means if you're displaying UI to your users you must ensure
30+
that any windows (or any resource sharing for that matter) are
31+
created in the right thread context or bad things might happen.
32+
Test this behavior well before releasing to your end-users.
33+
'''
34+
def trial_callback(status, unused):
35+
36+
if status == TA_CB_EXPIRED:
37+
# TODO: disallow any features in your app.
38+
print("The app trial period has expired")
39+
40+
elif status == TA_CB_EXPIRED_FRAUD:
41+
# TODO: disallow any features in your app.
42+
print("The lease has been dropped due to computer sleeping.")
43+
44+
else:
45+
print("The app trial callback returned an unexpected status: ", status)
46+
47+
2348
if __name__ == "__main__":
2449

2550
# support both Python 2 and 3
@@ -105,7 +130,7 @@
105130
# Start or re-validate the trial if it has already started.
106131
# This need to be called at least once before you can use
107132
# any other trial functions.
108-
ta.use_trial(verified_trial)
133+
ta.use_trial(verified_trial, "", trial_callback)
109134

110135
# Get the number of trial days remaining.
111136
trial_days = ta.trial_days_remaining(verified_trial)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from distutils.core import setup
55

66
setup(name="turboactivate",
7-
version="4.4.4",
7+
version="4.4.4.1",
88
description="Python integration for the LimeLM TurboActivate library. This lets you add hardware-locked licensing (a.k.a. node-locked licensing) to your Python app.",
99
url="https://wyday.com/limelm/help/using-turboactivate-with-python/",
1010
download_url="https://github.com/wyday/python-turboactivate",

turboactivate/__init__.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
3232
# IN THE SOFTWARE.
3333

34-
from ctypes import pointer, sizeof, c_uint32
34+
from ctypes import pointer, sizeof, c_uint32, c_void_p
3535

3636
from turboactivate.c_wrapper import *
3737

@@ -133,17 +133,14 @@ def get_pkey(self):
133133

134134
def deactivate(self, erase_p_key=False):
135135
"""
136-
Deactivates the product on this computer. Set erasePkey to 1 to erase the stored
137-
product key, 0 to keep the product key around. If you're using deactivate to let
138-
a user move between computers it's almost always best to *not* erase the product
139-
key. This way you can just use TA_Activate() when the user wants to reactivate
140-
instead of forcing the user to re-enter their product key over-and-over again.
136+
Deactivates the product on this computer. Set erasePkey to 1 to erase the stored
137+
product key, 0 to keep the product key around. If you're using deactivate to let
138+
a user move between computers it's almost always best to *not* erase the product
139+
key. This way you can just use TA_Activate() when the user wants to reactivate
140+
instead of forcing the user to re-enter their product key over-and-over again.
141141
"""
142142

143-
if erase_p_key is True:
144-
args = 1
145-
else:
146-
args = 0
143+
args = 1 if erase_p_key else 0
147144

148145
self._lib.TA_Deactivate(self._handle, args)
149146

@@ -304,7 +301,7 @@ def is_genuine_ex(self, days_between_checks, grace_days_on_inet_err, skip_offlin
304301

305302
# Trial
306303

307-
def use_trial(self, verified=True, extra_data=""):
304+
def use_trial(self, verified=True, extra_data="", callback = None):
308305
"""
309306
Begins the trial the first time it's called. Calling it again will validate the trial
310307
data hasn't been tampered with.
@@ -318,6 +315,14 @@ def use_trial(self, verified=True, extra_data=""):
318315
else:
319316
args.append(None)
320317

318+
# Set the trial callback
319+
if callback is not None:
320+
# "cast" the native python function to TrialCallback type
321+
# save it locally so that it acutally works when it's called
322+
# back
323+
self._callback = TrialCallback(callback)
324+
self._lib.TA_SetTrialCallback(self._handle, self._callback, c_void_p(0))
325+
321326
self._lib.TA_UseTrial(self._handle, *args)
322327

323328
def trial_days_remaining(self, verified=True):
@@ -425,3 +430,4 @@ def _set_restype(self):
425430
self._lib.TA_IsDateValid.restype = validate_result
426431
self._lib.TA_SetCustomProxy.restype = validate_result
427432
self._lib.TA_SetCustomActDataPath.restype = validate_result
433+
self._lib.TA_SetTrialCallback.restype = validate_result

turboactivate/c_wrapper.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
#
33
# Copyright 2013, 2014 Develer S.r.l. (https://www.develer.com/)
4-
# Copyright 2018 wyDay, LLC (https://wyday.com/)
4+
# Copyright 2021 wyDay, LLC (https://wyday.com/)
55
#
66
# Current Author / maintainer:
77
#
@@ -36,11 +36,14 @@
3636
from ctypes import (
3737
cdll,
3838
c_uint,
39+
c_uint32,
40+
c_void_p,
3941
c_char_p,
4042
c_wchar_p,
4143
Structure,
4244
create_string_buffer,
43-
create_unicode_buffer
45+
create_unicode_buffer,
46+
CFUNCTYPE
4447
)
4548

4649
# Utilities
@@ -166,6 +169,19 @@ def __init__(self, string):
166169
TA_HAS_NOT_EXPIRED = 0x00000001
167170

168171

172+
# Possible callback statuses from the TrialCallbackType function:
173+
174+
'''
175+
Callback-status value used when the trial has expired.
176+
'''
177+
TA_CB_EXPIRED = 0x00000000
178+
179+
'''
180+
Callback-status value used when the trial has expired due to date/time fraud.
181+
'''
182+
TA_CB_EXPIRED_FRAUD = 0x00000001
183+
184+
169185
class GENUINE_OPTIONS(Structure):
170186
_fields_ = [
171187
("nLength", c_uint),
@@ -182,6 +198,8 @@ class ACTIVATE_OPTIONS(Structure):
182198
]
183199

184200

201+
TrialCallback = CFUNCTYPE(None, c_uint32, c_void_p)
202+
185203
def load_library(path):
186204

187205
if sys.platform == 'win32' or sys.platform == 'cygwin':

0 commit comments

Comments
 (0)