Skip to content

Commit

Permalink
Prefer setuptools imports to distutils imports
Browse files Browse the repository at this point in the history
The non-conditional imports have been around for 6 to 17 years,
so they should be safe in conservative situations too.

Refs #824
  • Loading branch information
akx committed Apr 8, 2022
1 parent 7e90d6b commit 5aa000e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 59 deletions.
94 changes: 54 additions & 40 deletions babel/messages/frontend.py
Expand Up @@ -32,9 +32,23 @@
from babel.messages.mofile import write_mo
from babel.messages.pofile import read_po, write_po
from babel.util import LOCALTZ
from distutils import log as distutils_log
from distutils.cmd import Command as _Command
from distutils.errors import DistutilsOptionError, DistutilsSetupError

log = logging.getLogger('babel')

try:
# See: https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html
from setuptools import Command as _Command
distutils_log = log # "distutils.log → (no replacement yet)"

try:
from setuptools.errors import OptionError, SetupError
except ImportError: # Error aliases only added in setuptools 59 (2021-11).
OptionError = SetupError = Exception

except ImportError:
from distutils import log as distutils_log
from distutils.cmd import Command as _Command
from distutils.errors import OptionError as OptionError, DistutilsSetupError as SetupError


def listify_value(arg, split=None):
Expand Down Expand Up @@ -169,11 +183,9 @@ def initialize_options(self):
def finalize_options(self):
self.domain = listify_value(self.domain)
if not self.input_file and not self.directory:
raise DistutilsOptionError('you must specify either the input file '
'or the base directory')
raise OptionError('you must specify either the input file or the base directory')
if not self.output_file and not self.directory:
raise DistutilsOptionError('you must specify either the output file '
'or the base directory')
raise OptionError('you must specify either the output file or the base directory')

def run(self):
n_errors = 0
Expand Down Expand Up @@ -216,7 +228,7 @@ def _run_domain(self, domain):
domain + '.mo'))

if not po_files:
raise DistutilsOptionError('no message catalogs found')
raise OptionError('no message catalogs found')

catalogs_and_errors = {}

Expand Down Expand Up @@ -388,7 +400,7 @@ def finalize_options(self):
if not self.input_paths:
self.input_paths = self.input_dirs
else:
raise DistutilsOptionError(
raise OptionError(
'input-dirs and input-paths are mutually exclusive'
)

Expand All @@ -402,22 +414,25 @@ def finalize_options(self):
self.keywords = keywords

if not self.keywords:
raise DistutilsOptionError('you must specify new keywords if you '
'disable the default ones')
raise OptionError(
'you must specify new keywords if you disable the default ones'
)

if not self.output_file:
raise DistutilsOptionError('no output file specified')
raise OptionError('no output file specified')
if self.no_wrap and self.width:
raise DistutilsOptionError("'--no-wrap' and '--width' are mutually "
"exclusive")
raise OptionError(
"'--no-wrap' and '--width' are mutually exclusive"
)
if not self.no_wrap and not self.width:
self.width = 76
elif self.width is not None:
self.width = int(self.width)

if self.sort_output and self.sort_by_file:
raise DistutilsOptionError("'--sort-output' and '--sort-by-file' "
"are mutually exclusive")
raise OptionError(
"'--sort-output' and '--sort-by-file' are mutually exclusive"
)

if self.input_paths:
if isinstance(self.input_paths, str):
Expand All @@ -431,11 +446,11 @@ def finalize_options(self):
self.input_paths = []

if not self.input_paths:
raise DistutilsOptionError("no input files or directories specified")
raise OptionError("no input files or directories specified")

for path in self.input_paths:
if not os.path.exists(path):
raise DistutilsOptionError("Input path: %s does not exist" % path)
raise OptionError("Input path: %s does not exist" % path)

self.add_comments = listify_value(self.add_comments or (), ",")

Expand All @@ -456,7 +471,6 @@ def finalize_options(self):
else:
self.directory_filter = None


def run(self):
mappings = self._get_mappings()
with open(self.output_file, 'wb') as outfile:
Expand Down Expand Up @@ -558,8 +572,10 @@ def check_message_extractors(dist, name, value):
"""
assert name == 'message_extractors'
if not isinstance(value, dict):
raise DistutilsSetupError('the value of the "message_extractors" '
'parameter must be a dictionary')
raise SetupError(
'the value of the "message_extractors" '
'parameter must be a dictionary'
)


class init_catalog(Command):
Expand Down Expand Up @@ -609,27 +625,25 @@ def initialize_options(self):

def finalize_options(self):
if not self.input_file:
raise DistutilsOptionError('you must specify the input file')
raise OptionError('you must specify the input file')

if not self.locale:
raise DistutilsOptionError('you must provide a locale for the '
'new catalog')
raise OptionError('you must provide a locale for the new catalog')
try:
self._locale = Locale.parse(self.locale)
except UnknownLocaleError as e:
raise DistutilsOptionError(e)
raise OptionError(e) from e

if not self.output_file and not self.output_dir:
raise DistutilsOptionError('you must specify the output directory')
raise OptionError('you must specify the output directory')
if not self.output_file:
self.output_file = os.path.join(self.output_dir, self.locale,
'LC_MESSAGES', self.domain + '.po')

if not os.path.exists(os.path.dirname(self.output_file)):
os.makedirs(os.path.dirname(self.output_file))
if self.no_wrap and self.width:
raise DistutilsOptionError("'--no-wrap' and '--width' are mutually "
"exclusive")
raise OptionError("'--no-wrap' and '--width' are mutually exclusive")
if not self.no_wrap and not self.width:
self.width = 76
elif self.width is not None:
Expand Down Expand Up @@ -723,28 +737,28 @@ def initialize_options(self):

def finalize_options(self):
if not self.input_file:
raise DistutilsOptionError('you must specify the input file')
raise OptionError('you must specify the input file')
if not self.output_file and not self.output_dir:
raise DistutilsOptionError('you must specify the output file or '
'directory')
raise OptionError('you must specify the output file or directory')
if self.output_file and not self.locale:
raise DistutilsOptionError('you must specify the locale')
raise OptionError('you must specify the locale')

if self.init_missing:
if not self.locale:
raise DistutilsOptionError('you must specify the locale for '
'the init-missing option to work')
raise OptionError(
'you must specify the locale for '
'the init-missing option to work'
)

try:
self._locale = Locale.parse(self.locale)
except UnknownLocaleError as e:
raise DistutilsOptionError(e)
raise OptionError(e) from e
else:
self._locale = None

if self.no_wrap and self.width:
raise DistutilsOptionError("'--no-wrap' and '--width' are mutually "
"exclusive")
raise OptionError("'--no-wrap' and '--width' are mutually exclusive")
if not self.no_wrap and not self.width:
self.width = 76
elif self.width is not None:
Expand All @@ -771,7 +785,7 @@ def run(self):
po_files.append((self.locale, self.output_file))

if not po_files:
raise DistutilsOptionError('no message catalogs found')
raise OptionError('no message catalogs found')

domain = self.domain
if not domain:
Expand Down Expand Up @@ -910,7 +924,7 @@ def run(self, argv=None):
return cmdinst.run()

def _configure_logging(self, loglevel):
self.log = logging.getLogger('babel')
self.log = log
self.log.setLevel(loglevel)
# Don't add a new handler for every instance initialization (#227), this
# would cause duplicated output when the CommandLineInterface as an
Expand Down Expand Up @@ -976,7 +990,7 @@ def _configure_command(self, cmdname, argv):

try:
cmdinst.ensure_finalized()
except DistutilsOptionError as err:
except OptionError as err:
parser.error(str(err))

return cmdinst
Expand Down
3 changes: 1 addition & 2 deletions setup.py
Expand Up @@ -2,9 +2,8 @@

import subprocess
import sys
from distutils.cmd import Command

from setuptools import setup
from setuptools import setup, Command

try:
from babel import __version__
Expand Down
29 changes: 12 additions & 17 deletions tests/messages/test_frontend.py
Expand Up @@ -11,12 +11,10 @@
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.
import shlex
from freezegun import freeze_time
from datetime import datetime
from distutils.dist import Distribution
from distutils.errors import DistutilsOptionError
from distutils.log import _global_log
from freezegun import freeze_time
from io import StringIO
from setuptools import Distribution
import logging
import os
import shutil
Expand All @@ -29,7 +27,7 @@
from babel import __version__ as VERSION
from babel.dates import format_datetime
from babel.messages import frontend, Catalog
from babel.messages.frontend import CommandLineInterface, extract_messages, update_catalog
from babel.messages.frontend import CommandLineInterface, extract_messages, update_catalog, OptionError
from babel.util import LOCALTZ
from babel.messages.pofile import read_po, write_po

Expand All @@ -49,7 +47,6 @@ class CompileCatalogTestCase(unittest.TestCase):
def setUp(self):
self.olddir = os.getcwd()
os.chdir(data_dir)
_global_log.threshold = 5 # shut up distutils logging

self.dist = Distribution(dict(
name='TestProject',
Expand All @@ -65,20 +62,19 @@ def tearDown(self):
def test_no_directory_or_output_file_specified(self):
self.cmd.locale = 'en_US'
self.cmd.input_file = 'dummy'
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_no_directory_or_input_file_specified(self):
self.cmd.locale = 'en_US'
self.cmd.output_file = 'dummy'
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)


class ExtractMessagesTestCase(unittest.TestCase):

def setUp(self):
self.olddir = os.getcwd()
os.chdir(data_dir)
_global_log.threshold = 5 # shut up distutils logging

self.dist = Distribution(dict(
name='TestProject',
Expand All @@ -100,21 +96,21 @@ def assert_pot_file_exists(self):
def test_neither_default_nor_custom_keywords(self):
self.cmd.output_file = 'dummy'
self.cmd.no_default_keywords = True
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_no_output_file_specified(self):
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_both_sort_output_and_sort_by_file(self):
self.cmd.output_file = 'dummy'
self.cmd.sort_output = True
self.cmd.sort_by_file = True
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_invalid_file_or_dir_input_path(self):
self.cmd.input_paths = 'nonexistent_path'
self.cmd.output_file = 'dummy'
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_input_paths_is_treated_as_list(self):
self.cmd.input_paths = data_dir
Expand Down Expand Up @@ -146,7 +142,7 @@ def test_input_dirs_is_mutually_exclusive_with_input_paths(self):
self.cmd.input_dirs = this_dir
self.cmd.input_paths = this_dir
self.cmd.output_file = pot_file
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

@freeze_time("1994-11-11")
def test_extraction_with_default_mapping(self):
Expand Down Expand Up @@ -354,7 +350,6 @@ class InitCatalogTestCase(unittest.TestCase):
def setUp(self):
self.olddir = os.getcwd()
os.chdir(data_dir)
_global_log.threshold = 5 # shut up distutils logging

self.dist = Distribution(dict(
name='TestProject',
Expand All @@ -375,12 +370,12 @@ def tearDown(self):
def test_no_input_file(self):
self.cmd.locale = 'en_US'
self.cmd.output_file = 'dummy'
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

def test_no_locale(self):
self.cmd.input_file = 'dummy'
self.cmd.output_file = 'dummy'
self.assertRaises(DistutilsOptionError, self.cmd.finalize_options)
self.assertRaises(OptionError, self.cmd.finalize_options)

@freeze_time("1994-11-11")
def test_with_output_dir(self):
Expand Down

0 comments on commit 5aa000e

Please sign in to comment.