diff --git a/requirements.txt b/requirements.txt index 5e53e75..1c1d0ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,7 @@ pypubsub==3.3.0 requests-oauthlib future arrow -yandex.translate \ No newline at end of file +yandex.translate +# forked repositories previously found at http://q-continuum.net +git+https://code.manuelcortez.net/manuelcortez/libloader +git+https://code.manuelcortez.net/manuelcortez/accessible_output2 \ No newline at end of file diff --git a/src/accessible_output2/__init__.py b/src/accessible_output2/__init__.py deleted file mode 100644 index c826e7a..0000000 --- a/src/accessible_output2/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import -import ctypes -import os -import types -from platform_utils import paths - -def load_library(libname, cdll=False): - if paths.is_frozen(): - libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname) - else: - libfile = os.path.join(paths.module_path(), 'lib', libname) - if cdll: - return ctypes.cdll[libfile] - else: - return ctypes.windll[libfile] - -def get_output_classes(): - from . import outputs - module_type = types.ModuleType - classes = [m.output_class for m in outputs.__dict__.values() if type(m) == module_type and hasattr(m, 'output_class')] - return sorted(classes, key=lambda c: c.priority) - -def find_datafiles(): - import os - import platform - from glob import glob - import accessible_output2 - if platform.system() != 'Windows': - return [] - path = os.path.join(accessible_output2.__path__[0], 'lib', '*.dll') - results = glob(path) - dest_dir = os.path.join('accessible_output2', 'lib') - return [(dest_dir, results)] diff --git a/src/accessible_output2/lib/PCTKUSR.dll b/src/accessible_output2/lib/PCTKUSR.dll deleted file mode 100644 index 82cc23a..0000000 Binary files a/src/accessible_output2/lib/PCTKUSR.dll and /dev/null differ diff --git a/src/accessible_output2/lib/PCTKUSR64.dll b/src/accessible_output2/lib/PCTKUSR64.dll deleted file mode 100644 index 614f282..0000000 Binary files a/src/accessible_output2/lib/PCTKUSR64.dll and /dev/null differ diff --git a/src/accessible_output2/lib/SAAPI32.dll b/src/accessible_output2/lib/SAAPI32.dll deleted file mode 100644 index 166f7d3..0000000 Binary files a/src/accessible_output2/lib/SAAPI32.dll and /dev/null differ diff --git a/src/accessible_output2/lib/dolapi.dll b/src/accessible_output2/lib/dolapi.dll deleted file mode 100644 index c77f215..0000000 Binary files a/src/accessible_output2/lib/dolapi.dll and /dev/null differ diff --git a/src/accessible_output2/lib/nvdaControllerClient32.dll b/src/accessible_output2/lib/nvdaControllerClient32.dll deleted file mode 100644 index 1d061b1..0000000 Binary files a/src/accessible_output2/lib/nvdaControllerClient32.dll and /dev/null differ diff --git a/src/accessible_output2/lib/nvdaControllerClient64.dll b/src/accessible_output2/lib/nvdaControllerClient64.dll deleted file mode 100644 index 6b4fff7..0000000 Binary files a/src/accessible_output2/lib/nvdaControllerClient64.dll and /dev/null differ diff --git a/src/accessible_output2/outputs/__init__.py b/src/accessible_output2/outputs/__init__.py deleted file mode 100644 index d0b9a48..0000000 --- a/src/accessible_output2/outputs/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import absolute_import -import platform -if platform.system() == 'Windows': - from . import nvda - from . import jaws - from . import sapi5 - from . import window_eyes - from . import system_access - from . import dolphin - from . import pc_talker - #import sapi4 - -if platform.system() == 'Darwin': - from . import voiceover - from . import say - -if platform.system() == 'Linux': - from . import e_speak - -from . import auto diff --git a/src/accessible_output2/outputs/auto.py b/src/accessible_output2/outputs/auto.py deleted file mode 100644 index 8026fce..0000000 --- a/src/accessible_output2/outputs/auto.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import absolute_import -import accessible_output2 -from .base import Output, OutputError - -class Auto(Output): - - def __init__(self): - output_classes = accessible_output2.get_output_classes() - self.outputs = [] - for output in output_classes: - try: - self.outputs.append(output()) - except OutputError: - pass - - def get_first_available_output(self): - for output in self.outputs: - if output.is_active(): - return output - return None - - def speak(self, *args, **kwargs): - output = self.get_first_available_output() - if output: - output.speak(*args, **kwargs) - - def braille(self, *args, **kwargs): - output = self.get_first_available_output() - if output: - output.braille(*args, **kwargs) - - def output(self, *args, **kwargs): - output = self.get_first_available_output() - if output: - output.speak(*args, **kwargs) - - def is_system_output(self): - output = self.get_first_available_output() - if output: - return output.is_system_output() diff --git a/src/accessible_output2/outputs/base.py b/src/accessible_output2/outputs/base.py deleted file mode 100644 index 2847f2f..0000000 --- a/src/accessible_output2/outputs/base.py +++ /dev/null @@ -1,47 +0,0 @@ -from accessible_output2 import load_library -import platform - -class OutputError(Exception): - pass - -class Output(object): - name = "Unnamed Output" - lib32 = None - lib64 = None - argtypes = {} - cdll = False - priority = 100 - system_output = False - - def __init__(self): - self.is_32bit = platform.architecture()[0] == "32bit" - if self.lib32 and self.is_32bit: - self.lib = load_library(self.lib32, cdll=self.cdll) - elif self.lib64: - self.lib = load_library(self.lib64, cdll=self.cdll) - else: - self.lib = None - if self.lib is not None: - for func in self.argtypes: - try: - getattr(self.lib, func).argtypes = self.argtypes[func] - except AttributeError: - pass - - def output(self, text, **options): - output = False - if self.speak(text, **options): - output = True - if self.braille(text, **options): - output = True - if not output: - raise RuntimeError("Output %r does not have any method defined to output" % self) - - def is_system_output(self): - return self.system_output - - def speak(self, **optiont): - return False - - def braille(self, *args, **options): - return False diff --git a/src/accessible_output2/outputs/dolphin.py b/src/accessible_output2/outputs/dolphin.py deleted file mode 100644 index 4d4efb6..0000000 --- a/src/accessible_output2/outputs/dolphin.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import -import os -import ctypes - -from .base import Output - -class Dolphin (Output): - """Supports dolphin products.""" - - name = 'Dolphin' - lib32 = 'dolapi.dll' - argtypes = { - 'DolAccess_Command': (ctypes.c_wchar_p, ctypes.c_int, ctypes.c_int), - 'DolAccess_Action': (ctypes.c_int,), - } - - def speak(self, text, interrupt=0): - if interrupt: - self.silence() - #If we don't call this, the API won't let us speak. - if self.is_active(): - self.lib.DolAccess_Command(text, (len(text)*2)+2, 1) - - def silence(self): - self.lib.DolAccess_Action(141) - - def is_active(self): - try: - return self.lib.DolAccess_GetSystem() in (1, 4, 8) - except: - return False - -output_class = Dolphin diff --git a/src/accessible_output2/outputs/e_speak.py b/src/accessible_output2/outputs/e_speak.py deleted file mode 100644 index 6c60b95..0000000 --- a/src/accessible_output2/outputs/e_speak.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import absolute_import -from .base import Output - -try: - import espeak.core -except: - raise RuntimeError("Cannot find espeak.core. Please install python-espeak") - -class ESpeak(Output): - """Speech output supporting ESpeak on Linux - Note this requires python-espeak to be installed - This can be done on Debian distros by using apt-get install python-espeak - Or through this tarball: https://launchpad.net/python-espeak - """ - name = "Linux ESpeak" - - def is_active(self): - try: - import espeak.core - except: - return False - return True - - def speak(self, text, interrupt = 0): - if interrupt: - self.silence() - espeak.core.synth(text) - def silence(self): - espeak.core.cancel() - -output_class = ESpeak diff --git a/src/accessible_output2/outputs/jaws.py b/src/accessible_output2/outputs/jaws.py deleted file mode 100644 index 18a38df..0000000 --- a/src/accessible_output2/outputs/jaws.py +++ /dev/null @@ -1,34 +0,0 @@ -from __future__ import absolute_import -import win32gui -from libloader.com import load_com -import pywintypes - -from .base import Output, OutputError - -class Jaws (Output): - """Output supporting the Jaws for Windows screen reader.""" - - name = 'jaws' - - def __init__(self, *args, **kwargs): - super (Jaws, self).__init__(*args, **kwargs) - try: - self.object = load_com("FreedomSci.JawsApi", "jfwapi") - except pywintypes.com_error: - raise OutputError - - def braille(self, text, **options): - # HACK: replace " with ', Jaws doesn't seem to understand escaping them with \ - text = text.replace('"', "'") - self.object.RunFunction("BrailleString(\"%s\")" % text) - - def speak(self, text, interrupt=False): - self.object.SayString(' %s' % text, interrupt) - - def is_active(self): - try: - return self.object.SayString('',0) == True or win32gui.FindWindow("JFWUI2", "JAWS") != 0 - except: - return False - -output_class = Jaws diff --git a/src/accessible_output2/outputs/nvda.py b/src/accessible_output2/outputs/nvda.py deleted file mode 100644 index 5affba3..0000000 --- a/src/accessible_output2/outputs/nvda.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import absolute_import -import os -import platform -import ctypes - -from platform_utils import paths -from libloader import load_library -from .base import Output - -class NVDA(Output): - """Supports The NVDA screen reader""" - name = "NVDA" - lib32 = 'nvdaControllerClient32.dll' - lib64 = 'nvdaControllerClient64.dll' - argtypes = { - 'nvdaController_brailleMessage': (ctypes.c_wchar_p,), - 'nvdaController_speakText': (ctypes.c_wchar_p,), - } - - def is_active(self): - try: - return self.lib.nvdaController_testIfRunning() == 0 - except: - return False - - def braille(self, text, **options): - self.lib.nvdaController_brailleMessage(text) - - def speak(self, text, interrupt=False): - if interrupt: - self.silence() - self.lib.nvdaController_speakText(text) - - def silence(self): - self.lib.nvdaController_cancelSpeech() - -output_class = NVDA diff --git a/src/accessible_output2/outputs/pc_talker.py b/src/accessible_output2/outputs/pc_talker.py deleted file mode 100644 index ebdb043..0000000 --- a/src/accessible_output2/outputs/pc_talker.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import absolute_import -import ctypes -from .base import Output - -class PCTalker(Output): - lib32 = 'pctkusr.dll' - lib64 = 'pctkusr64.dll' - cdll = True - argtypes = { - 'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int) - } - - def speak(self, text, interrupt=False): - if interrupt: - self.silence() - self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1) - - def silence(self): - self.lib.PCTKVReset() - - def is_active(self): - return self.lib.PCTKStatus() != 0 - -output_class = PCTalker diff --git a/src/accessible_output2/outputs/sapi4.py b/src/accessible_output2/outputs/sapi4.py deleted file mode 100644 index 8f4c215..0000000 --- a/src/accessible_output2/outputs/sapi4.py +++ /dev/null @@ -1,143 +0,0 @@ -from __future__ import absolute_import -from builtins import range -from libloader.com import load_com -from .base import Output - -import logging -log = logging.getLogger(__name__) - -class Sapi4(Output): - - name = 'sapi4' - priority = 102 - - def __init__(self): - sapi4 = load_com("{EEE78591-FE22-11D0-8BEF-0060081841DE}") - self._voiceNo = sapi4.Find(0) - sapi4.Select(self._voiceNo) - sapi4.Speak(" ") - self.__object = sapi4 - self._voice_list = self._available_voices() - - def _set_capabilities(self): - sapi4 = self.__object - try: - sapi4.Pitch = sapi4.Pitch - self._min_pitch = sapi4.MinPitch - self._max_pitch = sapi4.MaxPitch - self._has_pitch = True - except: - self._min_pitch = 0 - self._max_pitch = 0 - self._has_pitch = False - try: - sapi4.Speed = sapi4.Speed - self._min_rate = sapi4.MinSpeed - self._max_rate = sapi4.MaxSpeed - self._has_rate = True - except: - self._min_rate = 0 - self._max_rate = 0 - self._has_rate = False - try: - sapi4.VolumeLeft = sapi4.VolumeLeft - self._min_volume = sapi4.MinVolumeLeft - self._max_volume = sapi4.MaxVolumeLeft - self._has_volume = True - except: - self._min_volume = 0 - self._max_volume = 0 - self._has_volume = False - - def _available_voices(self): - voice_list = [] - for voice_no in range(1, self.__object.CountEngines): - voice_list.append(self.__object.ModeName(voice_no)) - return voice_list - - @property - def available_voices(self): - return self._voice_list - - def list_voices(self): - return self.available_voices - - def get_voice(self): - return self.__object.ModeName(self._voice_no) - - def set_voice(self, value): - self._voice_no = self.list_voices().index(value) + 1 - self.__object.Select(self._voice_no) - self.silence() - self.__object.Speak(" ") - self._set_capabilities() - - def get_pitch(self): - if self.has_pitch: - return self.__object.Pitch - - def set_pitch(self, value): - if self.has_pitch: - self.__object.Pitch = value - - def get_rate(self): - if self.has_rate: - return self.__object.Speed - - def set_rate(self, value): - if self.has_rate: - self.__object.Speed = value - - def get_volume(self): - if self.has_volume: - return self.__object.VolumeLeft - - def set_volume(self, value): - if self.has_volume: - self.__object.VolumeLeft = value - - @property - def has_pitch(self): - return self._has_pitch - - @property - def has_rate(self): - return self._has_rate - - @property - def has_volume(self): - return self._has_volume - - @property - def min_pitch(self): - return self._min_pitch - - @property - def max_pitch(self): - return self._max_pitch - - @property - def min_rate(self): - return self._min_rate - - @property - def max_rate(self): - return self._max_rate - - @property - def min_volume(self): - return self._min_volume - - @property - def max_volume(self): - return self._max_volume - - def speak(self, text, interrupt=False): - if interrupt: - self.silence() - self.__object.Speak(text) - - def silence(self): - self.__object.AudioReset() - -output_class = Sapi4 diff --git a/src/accessible_output2/outputs/sapi5.py b/src/accessible_output2/outputs/sapi5.py deleted file mode 100644 index f75ab2a..0000000 --- a/src/accessible_output2/outputs/sapi5.py +++ /dev/null @@ -1,95 +0,0 @@ -from __future__ import absolute_import -from collections import OrderedDict -from libloader.com import load_com -from .base import Output, OutputError -import pywintypes -import logging -log = logging.getLogger(__name__) - -SVSFDefault = 0 -SVSFlagsAsync = 1 -SVSFPurgeBeforeSpeak = 2 -SVSFIsFilename = 4 -SVSFIsXML = 8 -SVSFIsNotXML = 16 -SVSFPersistXML = 32 - -class SAPI5(Output): - has_volume = True - has_rate = True - has_pitch = True - min_pitch = -10 - max_pitch = 10 - min_rate = -10 - max_rate = 10 - min_volume = 0 - max_volume = 100 - name = "sapi5" - priority = 101 - system_output = True - - def __init__(self): - try: - self.object = load_com("SAPI.SPVoice") - self._voices = self._available_voices() - except pywintypes.com_error: - raise OutputError - self._pitch = 0 - - def _available_voices(self): - _voices = OrderedDict() - for v in self.object.GetVoices(): - _voices[v.GetDescription()] = v - return _voices - - def list_voices(self): - return list(self._voices.keys()) - - def get_voice(self): - return self.object.Voice.GetDescription() - - def set_voice(self, value): - log.debug("Setting SAPI5 voice to \"%s\"" % value) - self.object.Voice = self._voices[value] - # For some reason SAPI5 does not reset audio after changing the voice - # By setting the audio device after changing voices seems to fix this - # This was noted from information at: - # http://lists.nvaccess.org/pipermail/nvda-dev/2011-November/022464.html - self.object.AudioOutput = self.object.AudioOutput - - def get_pitch(self): - return self._pitch - - def set_pitch(self, value): - log.debug("Setting pitch to %d" % value) - self._pitch = value - - def get_rate(self): - return self.object.Rate - - def set_rate(self, value): - log.debug("Setting rate to %d" % value) - self.object.Rate = value - - def get_volume(self): - return self.object.Volume - - def set_volume(self, value): - self.object.Volume = value - - def speak(self, text, interrupt=False): - if interrupt: - self.silence() - # We need to do the pitch in XML here - textOutput = "%s" % (round(self._pitch), text.replace("<", "<")) - self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML) - - def silence(self): - self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak) - - def is_active(self): - if self.object: - return True - return False - -output_class = SAPI5 diff --git a/src/accessible_output2/outputs/say.py b/src/accessible_output2/outputs/say.py deleted file mode 100644 index 5eb3bc4..0000000 --- a/src/accessible_output2/outputs/say.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import absolute_import -import os -from .base import Output - -class AppleSay(Output): - """Speech output supporting the Apple Say subsystem.""" - name = 'Apple Say' - def __init__(self, voice = 'Alex', rate = '300'): - self.voice = voice - self.rate = rate - super(AppleSay, self).__init__() - def is_active(self): - return not os.system('which say') - def speak(self, text, interrupt = 0): - if interrupt: - self.silence() - os.system('say -v %s -r %s "%s" &' % (self.voice, self.rate, text)) - def silence(self): - os.system('killall say') - -output_class = AppleSay \ No newline at end of file diff --git a/src/accessible_output2/outputs/system_access.py b/src/accessible_output2/outputs/system_access.py deleted file mode 100644 index f8f3d25..0000000 --- a/src/accessible_output2/outputs/system_access.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import absolute_import -import ctypes -from .base import Output - -class SystemAccess (Output): - """Supports System Access and System Access Mobile""" - - name = "System Access" - lib32 = 'saapi32.dll' - argtypes = { - 'SA_BrlShowTextW': (ctypes.c_wchar_p,), - 'SA_SayW': (ctypes.c_wchar_p,), - } - priority = 99 - - def braille(self, text, **options): - self.lib.SA_BrlShowTextW(text) - - def speak(self, text, interrupt=False): - if self.is_active(): - self.dll.SA_SayW(str(text)) - - def is_active(self): - try: - return self.dll.SA_IsRunning() - except: - return False - -output_class = SystemAccess diff --git a/src/accessible_output2/outputs/voiceover.py b/src/accessible_output2/outputs/voiceover.py deleted file mode 100644 index 6a432e3..0000000 --- a/src/accessible_output2/outputs/voiceover.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import absolute_import from builtins import str import subprocess, os from .base import Output class VoiceOver(Output): """Speech output supporting the Apple VoiceOver screen reader.""" def runAppleScript(self, command, process = 'voiceover'): return subprocess.Popen(['osascript', '-e', 'tell application "' + process + '"\n' + command + '\nend tell'], stdout = subprocess.PIPE).communicate()[0] name = 'VoiceOver' def speak(self, text, interrupt=0): if interrupt: self.silence() os.system('osascript -e \"tell application \\\"voiceover\\\" to output \\\"%s\\\"\" &' % text) def silence (self): self.runAppleScript('output ""') def is_active(self): return self.runAppleScript('return (name of processes) contains "VoiceOver"', 'system events').startswith('true') and not self.runAppleScript('try\nreturn bounds of vo cursor\non error\nreturn false\nend try').startswith('false') output_class = VoiceOver \ No newline at end of file diff --git a/src/accessible_output2/outputs/window_eyes.py b/src/accessible_output2/outputs/window_eyes.py deleted file mode 100644 index efed1b6..0000000 --- a/src/accessible_output2/outputs/window_eyes.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import -import win32gui -from libloader.com import load_com -from .base import Output, OutputError -import pywintypes - -class WindowEyes (Output): - """Speech output supporting the WindowEyes screen reader""" - - name = 'Window-Eyes' - - def __init__(self, *args, **kwargs): - super(WindowEyes, self).__init__(*args, **kwargs) - try: - self.object = load_com("gwspeak.speak") - except pywintypes.com_error: - raise OutputError - - def speak(self, text, interrupt=0): - if interrupt: - self.silence() - self.object.SpeakString(text) - - def silence (self): - self.object.Silence() - - def is_active(self): - try: - return win32gui.FindWindow("GWMExternalControl", "External Control") != 0 - except: - return False - -output_class = WindowEyes diff --git a/src/fixes/__init__.py b/src/fixes/__init__.py index 6b971bf..34956a9 100644 --- a/src/fixes/__init__.py +++ b/src/fixes/__init__.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- import sys -import fix_requests +from . import fix_requests + if hasattr(sys, "frozen"): - import fix_win32com + from . import fix_win32com + from . import fix_libloader def setup(): fix_requests.fix() if hasattr(sys, "frozen"): fix_win32com.fix() + fix_libloader.fix() \ No newline at end of file diff --git a/src/fixes/fix_libloader.py b/src/fixes/fix_libloader.py new file mode 100644 index 0000000..67f312a --- /dev/null +++ b/src/fixes/fix_libloader.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +import win32com +import paths +win32com.__gen_path__=paths.com_path() +import sys +import os +sys.path.append(os.path.join(win32com.__gen_path__, ".")) +from win32com.client import gencache +from pywintypes import com_error +from libloader import com + +fixed=False + +def patched_getmodule(modname): + mod=__import__(modname) + return sys.modules[modname] + +def load_com(*names): + global fixed + if fixed==False: + gencache._GetModule=patched_getmodule + com.prepare_gencache() + fixed=True + result = None + for name in names: + try: + result = gencache.EnsureDispatch(name) + break + except com_error: + continue + if result is None: + raise com_error("Unable to load any of the provided com objects.") + return result + +def fix(): + com.load_com = load_com \ No newline at end of file diff --git a/src/libloader/__init__.py b/src/libloader/__init__.py deleted file mode 100644 index b763538..0000000 --- a/src/libloader/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .libloader import * - -__version__ = 0.1 -__author__ = 'Christopher Toth ' -__doc__ = """ -Quickly and easily load shared libraries from various platforms. Also includes a libloader.com module for loading com modules on Windows. -""" diff --git a/src/libloader/com.py b/src/libloader/com.py deleted file mode 100644 index 82f13db..0000000 --- a/src/libloader/com.py +++ /dev/null @@ -1,40 +0,0 @@ -from pywintypes import com_error -import win32com -import paths -win32com.__gen_path__=paths.com_path() -import sys -import os -sys.path.append(os.path.join(win32com.__gen_path__, ".")) -from win32com.client import gencache -fixed=False - -def prepare_gencache(): - gencache.is_readonly = False - gencache.GetGeneratePath() - -def patched_getmodule(modname): - mod=__import__(modname) - return sys.modules[modname] - -def load_com(*names): - global fixed - if fixed==False: - gencache._GetModule=patched_getmodule - fixed=True - result = None - for name in names: - try: - result = gencache.EnsureDispatch(name) - break - except com_error: - continue - if result is None: - raise com_error("Unable to load any of the provided com objects.") - return result - - -def preexec(): - global fixed - if fixed==False: - gencache._GetModule=patched_getmodule - fixed=True diff --git a/src/libloader/libloader.py b/src/libloader/libloader.py deleted file mode 100644 index 6aa7c32..0000000 --- a/src/libloader/libloader.py +++ /dev/null @@ -1,56 +0,0 @@ -import ctypes -import collections -import platform -import os - -TYPES = { - 'Linux': { - 'loader': ctypes.CDLL, - 'functype': ctypes.CFUNCTYPE, - 'prefix': 'lib', - 'extension': '.so' - }, - 'Darwin': { - 'loader': ctypes.CDLL, - 'functype': ctypes.CFUNCTYPE, - 'prefix': 'lib', - 'extension': '.dylib' - }, -} -if platform.system() == 'Windows': - TYPES['Windows'] = { - 'loader': ctypes.WinDLL, - 'functype': ctypes.WINFUNCTYPE, - 'prefix': "", - 'extension': '.dll' - } - -class LibraryLoadError(OSError): pass - -def load_library(library, x86_path='.', x64_path='.', *args, **kwargs): - lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path) - loaded = _do_load(lib, *args, **kwargs) - if loaded is not None: - return loaded - raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib)) - -def _do_load(file, *args, **kwargs): - loader = TYPES[platform.system()]['loader'] - return loader(file, *args, **kwargs) - -def find_library_path(libname, x86_path='.', x64_path='.'): - libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname) - if platform.architecture()[0] == '64bit': - path = os.path.join(x64_path, libname) - else: - path = os.path.join(x86_path, libname) - ext = get_library_extension() - path = '%s%s' % (path, ext) - return os.path.abspath(path) - - -def get_functype(): - return TYPES[platform.system()]['functype'] - -def get_library_extension(): - return TYPES[platform.system()]['extension']