From 0b1cc8728cd65b6d0923004b3abdd22abaa41920 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Sun, 22 Sep 2024 17:31:28 -0500 Subject: [PATCH] Remove the Python 2.x-only Pyro dependency --- ChangeLog | 1 + TODO | 2 - setup.py | 2 - src/smartcard/pyro/PyroReader.py | 91 ------------- src/smartcard/pyro/__init__.py | 23 ---- src/smartcard/pyro/server/PyroDaemon.py | 92 ------------- src/smartcard/pyro/server/PyroEventServer.py | 104 --------------- src/smartcard/pyro/server/PyroNameServer.py | 124 ------------------ .../pyro/server/RemoteCardConnection.py | 42 ------ .../pyro/server/RemoteReaderServer.py | 118 ----------------- src/smartcard/pyro/server/__init__.py | 23 ---- 11 files changed, 1 insertion(+), 621 deletions(-) delete mode 100644 src/smartcard/pyro/PyroReader.py delete mode 100644 src/smartcard/pyro/__init__.py delete mode 100644 src/smartcard/pyro/server/PyroDaemon.py delete mode 100644 src/smartcard/pyro/server/PyroEventServer.py delete mode 100644 src/smartcard/pyro/server/PyroNameServer.py delete mode 100644 src/smartcard/pyro/server/RemoteCardConnection.py delete mode 100644 src/smartcard/pyro/server/RemoteReaderServer.py delete mode 100644 src/smartcard/pyro/server/__init__.py diff --git a/ChangeLog b/ChangeLog index 695595de..76ec7eb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Unreleased changes * Remove Python 2 conditional code * Migrate a `src/` layout. * Support only Python 3.9 and higher + * Remove the Python 2.x-only Pyro dependency * Migrate CI to use the official Coveralls action * Standardize local and CI testing to use tox * Build wheels in CI for all supported Python versions diff --git a/TODO b/TODO index 141856dd..d84da83b 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -- complete support of remote readers with Pyro and add in documentation - - document construction of standalone windows application using py2exe - documentation and implementation of card services diff --git a/setup.py b/setup.py index f2d79c65..11693a98 100644 --- a/setup.py +++ b/setup.py @@ -92,7 +92,6 @@ def run(self): 'python_requires': '>=3.9', 'packages': ["smartcard", "smartcard.pcsc", - "smartcard.pyro", "smartcard.reader", "smartcard.scard", "smartcard.sw", @@ -125,7 +124,6 @@ def run(self): + platform_swig_opts)], 'extras_require': { 'Gui': ['wxPython'], - 'Pyro': ['Pyro'], }, 'classifiers': [ diff --git a/src/smartcard/pyro/PyroReader.py b/src/smartcard/pyro/PyroReader.py deleted file mode 100644 index aeb746b6..00000000 --- a/src/smartcard/pyro/PyroReader.py +++ /dev/null @@ -1,91 +0,0 @@ -"""PyroReaderClient: concrete reader class for Remote Readers - -__author__ = "gemalto http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -import Pyro.core -import Pyro.naming - -from smartcard.Exceptions import NoCardException -from smartcard.reader.Reader import Reader - - -class PyroReader(Reader): - """Remote reader class.""" - def __init__(self, readername): - """Constructs a new Remote Reader client implementation from a - Pyro URI.""" - super().__init__(readername) - ns = Pyro.naming.NameServerLocator().getNS() - self.uri = ns.resolve(':pyscard.smartcard.readers.' + readername) - self.reader = Pyro.core.getAttrProxyForURI(self.uri) - self.name = self.reader.name - - def addtoreadergroup(self, groupname): - """Add reader to a reader group.""" - self.reader.addtoreadergroup(groupname) - - def removefromreadergroup(self, groupname): - """Remove a reader from a reader group""" - self.reader.removefromreadergroup(groupname) - - def createConnection(self): - """Return a card connection thru a remote reader.""" - uri = self.reader.createConnection() - return Pyro.core.getAttrProxyForURI(uri) - - class Factory: - def create(readername): - return PyroReader(readername) - create = staticmethod(create) - - def readers(groups=[]): - readernames = [] - try: - ns = Pyro.naming.NameServerLocator().getNS() - readernames = ns.list(':pyscard.smartcard.readers') - except Pyro.errors.NamingError: - print('Warning: pyro name server not found') - - remotereaders = [] - for readername in readernames: - remotereaders.append(PyroReader.Factory.create(readername[0])) - - return remotereaders - readers = staticmethod(readers) - -if __name__ == '__main__': - SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] - DF_TELECOM = [0x7F, 0x10] - from smartcard.util import * - - remotereaders = PyroReader.readers() - for reader in remotereaders: - try: - print(reader.name, ', uri: ', reader.uri) - connection = reader.createConnection() - connection.connect() - print(toHexString(connection.getATR())) - data, sw1, sw2 = connection.transmit(SELECT + DF_TELECOM) - print("{:X} {:X}".format(sw1, sw2)) - except NoCardException as x: - print('no card in reader') diff --git a/src/smartcard/pyro/__init__.py b/src/smartcard/pyro/__init__.py deleted file mode 100644 index 1c4e9225..00000000 --- a/src/smartcard/pyro/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -"""pyro (remote python) utility module. - -__author__ = "http://www.gemalto.com" - -Copyright 2011 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" diff --git a/src/smartcard/pyro/server/PyroDaemon.py b/src/smartcard/pyro/server/PyroDaemon.py deleted file mode 100644 index 847c1cf7..00000000 --- a/src/smartcard/pyro/server/PyroDaemon.py +++ /dev/null @@ -1,92 +0,0 @@ -"""PyroDaemon: Wrapper class around pyro daemon - -__author__ = "gemalto http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -import signal -from threading import Thread -import time - -import Pyro.core -import Pyro.naming - - -class PyroDaemon(object): - """Singleton class to wrap the pyro daemon.""" - - class _PyroDaemon: - """The pyro daemon actual wrapper class. - - A single instance of this class is created - by the public PyroDaemon class. - """ - def __init__(self): - self.daemon = Pyro.core.Daemon() - self.handler = signal.signal(signal.SIGINT, self) - ns = Pyro.naming.NameServerLocator().getNS() - self.daemon.useNameServer(ns) - - def __call__(self, signame, sf): - """Ctrl+c handler that will gracefully shutdown the server - upon Ctrl+C signal""" - print('PyroDaemon Ctrl+C handler') - self.daemon.shutdown(True) - time.sleep(1) - self.handler(signame, sf) - - def connect(self, object, name=None): - return self.daemon.connect(object, name) - - def disconnect(self, object): - return self.daemon.disconnect(object) - - def start(self): - """start pyro daemon.""" - self.daemon.requestLoop() - - # the singleton - instance = None - - def __init__(self): - if not PyroDaemon.instance: - PyroDaemon.instance = PyroDaemon._PyroDaemon() - - def __getattr__(self, name): - return getattr(self.instance, name) - - -class PyroDaemonThread(Thread): - """Thread running the Pyro daemon server. - """ - - def __init__(self): - """Initialize pyro event server with command line arguments. - For a complete list of command line arguments, see pyro documentation - for pyro-es start script.""" - Thread.__init__(self) - self.daemon = True - self.name = 'smartcard.pyro.server.PyroDaemonThread' - self.daemon = PyroDaemon() - - def run(self): - """Starts Pyro daemon.""" - self.daemon.start() diff --git a/src/smartcard/pyro/server/PyroEventServer.py b/src/smartcard/pyro/server/PyroEventServer.py deleted file mode 100644 index 17a8fb4f..00000000 --- a/src/smartcard/pyro/server/PyroEventServer.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Utility class to start/stop Pyro Event Server. - -__author__ = "http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -import signal -import sys -from threading import Thread -import time - -import Pyro.EventService.Server -import Pyro.naming -import Pyro.nsc -import Pyro.util - - -class PyroEventServer(Thread): - """Thread running the Pyro Event server. - """ - - def __init__(self, args=[]): - """Initialize pyro event server with command line arguments. - For a complete list of command line arguments, see pyro documentation - for pyro-es start script.""" - Thread.__init__(self) - self.daemon = True - self.name = 'smartcard.pyro.server.PyroEventServer' - self.args = args - self.handler = signal.signal(signal.SIGINT, self) - self.starter = None - - def run(self): - """Starts Pyro naming server with command line arguments (see - pyro documentation) """ - args = [] - for arg in self.args: - args.append(arg) - Args = Pyro.util.ArgParser() - Args.parse(args, 'hkmrvxn:p:b:c:d:s:i:1:2:') - - hostname = Args.getOpt('n', None) - identification = Args.getOpt('i', None) - port = None - useNameServer = True - - if port: - port = int(port) - norange = (port == 0) - - self.starter = Pyro.EventService.Server.EventServiceStarter( - identification=identification) - self.starter.start( - hostname, port, useNameServer=useNameServer, norange=norange) - - def stop(self): - """Shutdown pyro event server.""" - pass - - def waitStarted(self): - """wait until name server is started.""" - started = False - while not started: - if self.starter != None: - started = self.starter.waitUntilStarted(0.5) - - def __call__(self, signame, sf): - """Ctrl+c handler that will gracefully shutdown the server - upon Ctrl+C signal""" - print('PyroEventServer Ctrl+C handler') - self.stop() - time.sleep(1) - self.handler(signame, sf) - - -if __name__ == '__main__': - from smartcard.pyro.server.PyroNameServer import PyroNameServer - pn = PyroNameServer(sys.argv[1:]) - pn.start() - pn.waitStarted() - pe = PyroEventServer(sys.argv[1:]) - pe.start() - pe.waitStarted() - pn.listall() - pe.stop() - pn.stop() diff --git a/src/smartcard/pyro/server/PyroNameServer.py b/src/smartcard/pyro/server/PyroNameServer.py deleted file mode 100644 index 402efa43..00000000 --- a/src/smartcard/pyro/server/PyroNameServer.py +++ /dev/null @@ -1,124 +0,0 @@ -"""Utility class to start/stop Pyro Name Server. - -__author__ = "http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -import signal -import sys -from threading import Thread -import time - -import Pyro.naming -import Pyro.nsc -import Pyro.util - - -class PyroNameServer(Thread): - """Thread running the Pyro Name server. - """ - - def __init__(self, args=[]): - """Initialize pyro name server with command line arguments. - For a complete list of command line arguments, see pyro documentation - for pyro-ns start script.""" - Thread.__init__(self) - self.daemon = True - self.name = 'smartcard.pyro.server.PyroNameServer' - self.args = args - self.handler = signal.signal(signal.SIGINT, self) - - _args = [] - for arg in self.args: - _args.append(arg) - Args = Pyro.util.ArgParser() - Args.parse(_args, 'hkmrvxn:p:b:c:d:s:i:1:2:') - self.host = Args.getOpt('n', None) - self.bcport = Args.getOpt('b', None) - self.bcaddr = Args.getOpt('c', None) - self.identification = Args.getOpt('i', None) - - def getShutdownArgs(self): - """return command line arguments for shutting down the - server; this command line is built from the name server - startup arguments.""" - shutdownArgs = [] - if self.host: - shutdownArgs += ['-h', self.host] - if self.bcport: - shutdownArgs += ['-p', self.bcport] - if self.bcaddr: - shutdownArgs += ['-c', self.bcaddr] - if self.identification: - shutdownArgs += ['-i', self.identification] - - return shutdownArgs - - def listall(self): - """List pyro namespace.""" - args = self.getShutdownArgs() + ['listall'] - Pyro.nsc.main(args) - - def ping(self): - """Ping pyro naming server.""" - args = self.getShutdownArgs() + ['ping'] - Pyro.nsc.main(args) - - def run(self): - """Starts Pyro naming server with command line arguments - (see pyro documentation)""" - args = [] - for arg in self.args: - args.append(arg) - Pyro.naming.main(args) - - def stop(self): - """Shutdown pyro naming server.""" - args = self.getShutdownArgs() + ['shutdown'] - Pyro.nsc.main(args) - self.join() - - def waitStarted(self): - """wait until name server is started.""" - ns = None - while not ns: - try: - time.sleep(3) - ns = Pyro.naming.NameServerLocator( - identification=self.identification).getNS() - except Pyro.errors.NamingError as er: - pass - - def __call__(self, signame, sf): - """Ctrl+c handler that will gracefully shutdown the server - upon Ctrl+C signal""" - print('PyroNameServer Ctrl+C handler') - self.stop() - time.sleep(1) - self.handler(signame, sf) - - -if __name__ == '__main__': - import sys - pt = PyroNameServer(sys.argv[1:]) - pt.start() - pt.waitStarted() - pt.stop() diff --git a/src/smartcard/pyro/server/RemoteCardConnection.py b/src/smartcard/pyro/server/RemoteCardConnection.py deleted file mode 100644 index 2b092b7c..00000000 --- a/src/smartcard/pyro/server/RemoteCardConnection.py +++ /dev/null @@ -1,42 +0,0 @@ -"""RemoteCardConnection class manages connections to a remote reader -thru pyro (http://www.xs4all.nl/~irmen/pyro3/). - -__author__ = "http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -import Pyro.core -import Pyro.naming - -from smartcard.CardConnectionDecorator import CardConnectionDecorator - - -class RemoteCardConnection(CardConnectionDecorator, Pyro.core.ObjBase): - """Remote connection class. Handles connection with a card inserted - inside a remote PC.""" - - def __init__(self, cardConnectionComponent): - """Construct a new remote card connection. - - connection: the reader connection - """ - Pyro.core.ObjBase.__init__(self) - CardConnectionDecorator.__init__(self, cardConnectionComponent) diff --git a/src/smartcard/pyro/server/RemoteReaderServer.py b/src/smartcard/pyro/server/RemoteReaderServer.py deleted file mode 100644 index 33092d08..00000000 --- a/src/smartcard/pyro/server/RemoteReaderServer.py +++ /dev/null @@ -1,118 +0,0 @@ -"""RemoteReaderServer: monitor local readers and publish them as pyro -Remote Readers. - -__author__ = "gemalto http://www.gemalto.com" - -Copyright 2001-2012 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -""" - -try: - import Pyro.core - import Pyro.naming -except ImportError: - print('You need pyro (python remote objects) ' + \ - 'at http://www.xs4all.nl/~irmen/pyro3/') - import sys - sys.exit() - -from smartcard.reader.Reader import Reader -from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver -from smartcard.pyro.server.RemoteCardConnection import RemoteCardConnection -from smartcard.pyro.server import PyroDaemon -from smartcard.pyro.server import PyroNameServer - - -class RemoteReader(Reader, Pyro.core.ObjBase): - """Remote reader class that embeds a local reader.""" - - def __init__(self, reader): - """Encapsulate a local reader and publish as a pyro remote reader. - - reader: the local reader to publish remotely - """ - Pyro.core.ObjBase.__init__(self) - self.readerobj = reader - self.name = reader.name - - def addtoreadergroup(self, groupname): - """Add reader to a reader group.""" - self.readerobj.reader.addtoreadergroup(groupname) - - def removefromreadergroup(self, groupname): - """Remove a reader from a reader group""" - self.readerobj.reader.removefromreadergroup(groupname) - - def createConnection(self): - """Return a card connection thru the reader.""" - connection = RemoteCardConnection(self.readerobj.createConnection()) - daemon = PyroDaemon.PyroDaemon() - uri = daemon.connect(connection) - return uri - - -class RemoteReaderServer(ReaderObserver): - """Monitor local readers, and publish them as remote pyro readers. - """ - def __init__(self): - """Starts pyro name server and constructs reader name space.""" - self.pn = PyroNameServer.PyroNameServer() - self.pn.start() - self.pn.waitStarted() - - Pyro.core.initServer() - self.ns = Pyro.naming.NameServerLocator().getNS() - try: - self.ns.createGroup(':pyscard') - self.ns.createGroup(':pyscard.smartcard') - self.ns.createGroup(':pyscard.smartcard.readers') - except Pyro.errors.NamingError as error: - print(error) - self.daemon = PyroDaemon.PyroDaemon() - self.remotereaders = {} - - def start(self): - """Start pyro daemon and accept incoming requests.""" - self.daemon.start() - - def update(self, observable, actions): - """Called when a local reader is added or removed. - Create remote pyro reader objects for added readers. - Delete remote pyro reader objects for removed readers.""" - (addedreaders, removedreaders) = actions - for reader in addedreaders: - remotereader = RemoteReader(reader) - self.remotereaders[reader.name] = remotereader - name = "".join(reader.name.split(' ')) - name = ":pyscard.smartcard.readers." + "".join(name.split('.')) - uri = self.daemon.connect(remotereader, name) - for reader in removedreaders: - remotereader = self.remotereaders[reader.name] - self.daemon.disconnect(remotereader) - del self.remotereaders[reader.name] - self.pn.listall() - - -if __name__ == '__main__': - readerserver = RemoteReaderServer() - readermonitor = ReaderMonitor() - readermonitor.addObserver(readerserver) - print('Reader remote server up and running', end=' ') - print('Please enter Ctrl+C to stop and exit...') - readerserver.start() diff --git a/src/smartcard/pyro/server/__init__.py b/src/smartcard/pyro/server/__init__.py deleted file mode 100644 index f2621831..00000000 --- a/src/smartcard/pyro/server/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -"""pyro server utility module. - -__author__ = "http://www.gemalto.com" - -Copyright 2011 gemalto -Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com - -This file is part of pyscard. - -pyscard is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -pyscard is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with pyscard; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -"""