Avoids setup.py having to import the serial package.
It's bad practice for setup.py to import the package it is
installing in order to get, say, version information. For
example. if PYTHONPATH has been manipulated, the
import serial statement may not in fact import the
expected version.
This commit uses a technique for single-sourcing the
version number as recommended in the Python Packaging
Guide at
http://python-packaging-user-guide.readthedocs.io/en/latest/single_source_version/
In essence, we read serial.__init__.py as a text file and
parse it for the version number, rather than importing it.
diff --git a/setup.py b/setup.py
index 20c2a22..f2b60a6 100644
--- a/setup.py
+++ b/setup.py
@@ -9,14 +9,46 @@
# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
#
# SPDX-License-Identifier: BSD-3-Clause
+import io
+import os
+import re
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
-import serial
-version = serial.VERSION
+
+def read(*names, **kwargs):
+ """Python 2 and Python 3 compatible text file reading.
+
+ Required for single-sourcing the version string.
+ """
+ with io.open(
+ os.path.join(os.path.dirname(__file__), *names),
+ encoding=kwargs.get("encoding", "utf8")
+ ) as fp:
+ return fp.read()
+
+
+def find_version(*file_paths):
+ """
+ Search the file for a version string.
+
+ file_path contain string path components.
+
+ Reads the supplied Python module as text without importing it.
+ """
+ version_file = read(*file_paths)
+ version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
+ version_file, re.M)
+ if version_match:
+ return version_match.group(1)
+ raise RuntimeError("Unable to find version string.")
+
+
+version = find_version('serial', '__init__.py')
+
setup(
name="pyserial",