1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 12:41:29 +00:00

Convert ndiff and zenmap to setuptools. Fixes #2649

This commit is contained in:
dmiller
2024-01-29 17:09:26 +00:00
parent 4b80bfd34c
commit 19fc89840f
4 changed files with 41 additions and 52 deletions

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
import errno import errno
import sys import sys
@@ -8,13 +8,9 @@ import re
from stat import ST_MODE from stat import ST_MODE
import distutils.command import setuptools.command.install
import distutils.command.install from setuptools import setup, Command
import distutils.core import logging
import distutils.cmd
import distutils.errors
from distutils import log
from distutils.command.install import install
APP_NAME = "ndiff" APP_NAME = "ndiff"
# The name of the file used to record the list of installed files, so that the # The name of the file used to record the list of installed files, so that the
@@ -61,10 +57,10 @@ def path_strip_prefix(path, prefix):
############################################################################### ###############################################################################
# Distutils subclasses # setuptools subclasses
class null_command(distutils.cmd.Command): class null_command(Command):
"""This is a dummy distutils command that does nothing. We use it to """This is a dummy setuptools command that does nothing. We use it to
replace the install_egg_info and avoid installing a .egg-info file, because replace the install_egg_info and avoid installing a .egg-info file, because
there's no option to disable that.""" there's no option to disable that."""
def initialize_options(self): def initialize_options(self):
@@ -80,11 +76,7 @@ class null_command(distutils.cmd.Command):
pass pass
class checked_install(distutils.command.install.install): class checked_install(setuptools.command.install.install):
"""This is a wrapper around the install command that checks for an error
caused by not having the python-dev package installed. By default,
distutils gives a misleading error message: "invalid Python installation."
"""
def finalize_options(self): def finalize_options(self):
# Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in # Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in
@@ -92,15 +84,11 @@ class checked_install(distutils.command.install.install):
# default). Because we need the unchanged value later, remember it # default). Because we need the unchanged value later, remember it
# here. # here.
self.saved_prefix = sys.prefix self.saved_prefix = sys.prefix
try: super().finalize_options()
distutils.command.install.install.finalize_options(self)
except distutils.errors.DistutilsPlatformError as e:
raise distutils.errors.DistutilsPlatformError(str(e) + """
Installing your distribution's python-dev package may solve this problem.""")
def set_modules_path(self): def set_modules_path(self):
app_file_name = os.path.join(self.install_scripts, APP_NAME) app_file_name = os.path.join(self.install_scripts, APP_NAME)
# Find where the modules are installed. distutils will put them in # Find where the modules are installed. setuptools will put them in
# self.install_lib, but that path can contain the root (DESTDIR), so we # self.install_lib, but that path can contain the root (DESTDIR), so we
# must strip it off if necessary. # must strip it off if necessary.
modules_dir = self.install_lib modules_dir = self.install_lib
@@ -124,7 +112,7 @@ Installing your distribution's python-dev package may solve this problem.""")
app_file.close() app_file.close()
def run(self): def run(self):
install.run(self) super().run()
# These below are from Zenmap. We're only using set_modules_path right now, but # These below are from Zenmap. We're only using set_modules_path right now, but
# we might consider whether the others would be useful (or, if not, whether we # we might consider whether the others would be useful (or, if not, whether we
@@ -138,7 +126,7 @@ Installing your distribution's python-dev package may solve this problem.""")
def get_installed_files(self): def get_installed_files(self):
"""Return a list of installed files and directories, each prefixed with """Return a list of installed files and directories, each prefixed with
the installation root if given. The list of installed directories the installation root if given. The list of installed directories
doesn't come from distutils so it may be incomplete.""" doesn't come from setuptools so it may be incomplete."""
installed_files = self.get_outputs() installed_files = self.get_outputs()
for package in self.distribution.py_modules: for package in self.distribution.py_modules:
dir = package.replace(".", "/") dir = package.replace(".", "/")
@@ -236,7 +224,7 @@ for dir in dirs:
doesn't strip off the installation root, if any. File names containing doesn't strip off the installation root, if any. File names containing
newline characters are not handled.""" newline characters are not handled."""
if INSTALLED_FILES_NAME == self.record: if INSTALLED_FILES_NAME == self.record:
distutils.log.warn("warning: installation record is overwriting " logging.warning("warning: installation record is overwriting "
"--record file '%s'." % self.record) "--record file '%s'." % self.record)
with open(INSTALLED_FILES_NAME, "w") as f: with open(INSTALLED_FILES_NAME, "w") as f:
for output in self.get_installed_files(): for output in self.get_installed_files():
@@ -244,8 +232,8 @@ for dir in dirs:
print(output, file=f) print(output, file=f)
class my_uninstall(distutils.cmd.Command): class my_uninstall(Command):
"""A distutils command that performs uninstallation. It reads the list of """A setuptools command that performs uninstallation. It reads the list of
installed files written by the install command.""" installed files written by the install command."""
command_name = "uninstall" command_name = "uninstall"
@@ -265,8 +253,8 @@ class my_uninstall(distutils.cmd.Command):
f = open(INSTALLED_FILES_NAME, "r") f = open(INSTALLED_FILES_NAME, "r")
except IOError as e: except IOError as e:
if e.errno == errno.ENOENT: if e.errno == errno.ENOENT:
log.error("Couldn't open the installation record '%s'. " logging.error("Couldn't open the installation record '%s'. "
"Have you installed yet?" % INSTALLED_FILES_NAME) "Have you installed yet?", INSTALLED_FILES_NAME)
return return
installed_files = [file.rstrip("\n") for file in f.readlines()] installed_files = [file.rstrip("\n") for file in f.readlines()]
f.close() f.close()
@@ -282,29 +270,30 @@ class my_uninstall(distutils.cmd.Command):
dirs.append(path) dirs.append(path)
# Delete the files. # Delete the files.
for file in files: for file in files:
log.info("Removing '%s'." % file) logging.info("Removing '%s'.", file)
try: try:
if not self.dry_run: if not self.dry_run:
os.remove(file) os.remove(file)
except OSError as e: except OSError as e:
log.error(str(e)) logging.error(str(e))
# Delete the directories. First reverse-sort the normalized paths by # Delete the directories. First reverse-sort the normalized paths by
# length so that child directories are deleted before their parents. # length so that child directories are deleted before their parents.
dirs = [os.path.normpath(dir) for dir in dirs] dirs = [os.path.normpath(dir) for dir in dirs]
dirs.sort(key=len, reverse=True) dirs.sort(key=len, reverse=True)
for dir in dirs: for dir in dirs:
try: try:
log.info("Removing the directory '%s'." % dir) logging.info("Removing the directory '%s'.", dir)
if not self.dry_run: if not self.dry_run:
os.rmdir(dir) os.rmdir(dir)
except OSError as e: except OSError as e:
if e.errno == errno.ENOTEMPTY: if e.errno == errno.ENOTEMPTY:
log.info("Directory '%s' not empty; not removing." % dir) logging.info("Directory '%s' not empty; not removing.",
dir)
else: else:
log.error(str(e)) logging.error(str(e))
distutils.core.setup(name="ndiff", scripts=["scripts/ndiff"], setup(name="ndiff", scripts=["scripts/ndiff"],
py_modules=["ndiff"], py_modules=["ndiff"],
data_files=[("share/man/man1", ["docs/ndiff.1"])], data_files=[("share/man/man1", ["docs/ndiff.1"])],
cmdclass={ cmdclass={

View File

@@ -45,7 +45,7 @@ Default (source) Installation
* Double click the zenmap file * Double click the zenmap file
* Call the Python interpreter on the zenmap file * Call the Python interpreter on the zenmap file
Zenmap is packaged using Python distutils. To install Zenmap Zenmap is packaged using Python setuptools. To install Zenmap
independently of Nmap, enter the zenmap subdirectory and run independently of Nmap, enter the zenmap subdirectory and run
python setup.py install python setup.py install

View File

@@ -78,7 +78,7 @@ done
python -m compileall "$PYTHONLIB"/site-packages #|| true python -m compileall "$PYTHONLIB"/site-packages #|| true
echo "Stripping unoptimized Python libraries" echo "Stripping unoptimized Python libraries"
echo "Building using distutils" echo "Building using setuptools"
python3 setup.py build --executable "/usr/bin/env python3" python3 setup.py build --executable "/usr/bin/env python3"
python3 setup.py install vanilla --prefix "$BASE/Resources" python3 setup.py install vanilla --prefix "$BASE/Resources"

View File

@@ -64,10 +64,9 @@ import os
import os.path import os.path
import re import re
import distutils.sysconfig import logging
from distutils import log from setuptools import setup, Command
from distutils.core import setup, Command from setuptools.command.install import install
from distutils.command.install import install
from glob import glob from glob import glob
from stat import S_IRGRP, S_IROTH, S_IRUSR, S_IRWXU, S_IWUSR, S_IXGRP, S_IXOTH, ST_MODE from stat import S_IRGRP, S_IROTH, S_IRUSR, S_IRWXU, S_IWUSR, S_IXGRP, S_IXOTH, ST_MODE
@@ -189,7 +188,7 @@ class my_install(install):
def get_installed_files(self): def get_installed_files(self):
"""Return a list of installed files and directories, each prefixed with """Return a list of installed files and directories, each prefixed with
the installation root if given. The list of installed directories the installation root if given. The list of installed directories
doesn't come from distutils so it may be incomplete.""" doesn't come from setuptools so it may be incomplete."""
installed_files = self.get_outputs() installed_files = self.get_outputs()
for package in self.distribution.packages: for package in self.distribution.packages:
dir = package.replace(".", "/") dir = package.replace(".", "/")
@@ -290,7 +289,7 @@ for dir in dirs:
def set_modules_path(self): def set_modules_path(self):
app_file_name = os.path.join(self.install_scripts, APP_NAME) app_file_name = os.path.join(self.install_scripts, APP_NAME)
# Find where the modules are installed. distutils will put them in # Find where the modules are installed. setuptools will put them in
# self.install_lib, but that path can contain the root (DESTDIR), so we # self.install_lib, but that path can contain the root (DESTDIR), so we
# must strip it off if necessary. # must strip it off if necessary.
modules_dir = self.install_lib modules_dir = self.install_lib
@@ -412,7 +411,7 @@ for dir in dirs:
doesn't strip off the installation root, if any. File names containing doesn't strip off the installation root, if any. File names containing
newline characters are not handled.""" newline characters are not handled."""
if INSTALLED_FILES_NAME == self.record: if INSTALLED_FILES_NAME == self.record:
distutils.log.warn("warning: installation record is overwriting " logging.warning("warning: installation record is overwriting "
"--record file '%s'." % self.record) "--record file '%s'." % self.record)
with open(INSTALLED_FILES_NAME, "w") as f: with open(INSTALLED_FILES_NAME, "w") as f:
for output in self.get_installed_files(): for output in self.get_installed_files():
@@ -421,7 +420,7 @@ for dir in dirs:
class my_uninstall(Command): class my_uninstall(Command):
"""A distutils command that performs uninstallation. It reads the list of """A setuptools command that performs uninstallation. It reads the list of
installed files written by the install command.""" installed files written by the install command."""
command_name = "uninstall" command_name = "uninstall"
@@ -441,8 +440,8 @@ class my_uninstall(Command):
f = open(INSTALLED_FILES_NAME, "r") f = open(INSTALLED_FILES_NAME, "r")
except IOError as e: except IOError as e:
if e.errno == errno.ENOENT: if e.errno == errno.ENOENT:
log.error("Couldn't open the installation record '%s'. " logging.error("Couldn't open the installation record '%s'. "
"Have you installed yet?" % INSTALLED_FILES_NAME) "Have you installed yet?", INSTALLED_FILES_NAME)
return return
installed_files = [file.rstrip("\n") for file in f.readlines()] installed_files = [file.rstrip("\n") for file in f.readlines()]
f.close() f.close()
@@ -458,26 +457,27 @@ class my_uninstall(Command):
dirs.append(path) dirs.append(path)
# Delete the files. # Delete the files.
for file in files: for file in files:
log.info("Removing '%s'." % file) logging.info("Removing '%s'.", file)
try: try:
if not self.dry_run: if not self.dry_run:
os.remove(file) os.remove(file)
except OSError as e: except OSError as e:
log.error(str(e)) logging.error(str(e))
# Delete the directories. First reverse-sort the normalized paths by # Delete the directories. First reverse-sort the normalized paths by
# length so that child directories are deleted before their parents. # length so that child directories are deleted before their parents.
dirs = [os.path.normpath(dir) for dir in dirs] dirs = [os.path.normpath(dir) for dir in dirs]
dirs.sort(key=len, reverse=True) dirs.sort(key=len, reverse=True)
for dir in dirs: for dir in dirs:
try: try:
log.info("Removing the directory '%s'." % dir) logging.info("Removing the directory '%s'.", dir)
if not self.dry_run: if not self.dry_run:
os.rmdir(dir) os.rmdir(dir)
except OSError as e: except OSError as e:
if e.errno == errno.ENOTEMPTY: if e.errno == errno.ENOTEMPTY:
log.info("Directory '%s' not empty; not removing." % dir) logging.info("Directory '%s' not empty; not removing.",
dir)
else: else:
log.error(str(e)) logging.error(str(e))
# setup can be called in different ways depending on what we're doing. (For # setup can be called in different ways depending on what we're doing. (For
# example py2exe needs special handling.) These arguments are common between # example py2exe needs special handling.) These arguments are common between