def test_smart_tables(self): """Test :func:`humanfriendly.tables.format_smart_table()`.""" column_names = ['One', 'Two', 'Three'] data = [['1', '2', '3'], ['a', 'b', 'c']] assert ansi_strip(format_smart_table(data, column_names)) == dedent(""" --------------------- | One | Two | Three | --------------------- | 1 | 2 | 3 | | a | b | c | --------------------- """).strip() column_names = ['One', 'Two', 'Three'] data = [['1', '2', '3'], ['a', 'b', 'Here comes a\nmulti line column!']] assert ansi_strip(format_smart_table(data, column_names)) == dedent(""" ------------------ One: 1 Two: 2 Three: 3 ------------------ One: a Two: b Three: Here comes a multi line column! ------------------ """).strip()
def install_wsgi_app(self, python_code, *args, **kw): """ Install a temporary WSGI script file. :param python_code: A Python code template (a string). :param args: Positional arguments to be interpolated into the Python code. :param kw: Keyword arguments to be interpolated into the Python code. """ logger.info("Creating WSGI script: %s", self.wsgi_script_file) with open(self.wsgi_script_file, 'w') as handle: handle.write('%s\n' % dedent(python_code, *args, **kw)) logger.info("Creating Apache virtual host: %s", self.virtual_host_file) with open(self.virtual_host_file, 'w') as handle: netloc = self.manager.listen_addresses[0] handle.write( dedent(''' <VirtualHost {netloc.address}:{netloc.port}> ServerName {server_name} WSGIScriptAlias / {wsgi_script} </VirtualHost> ''', netloc=netloc, server_name=self.name, wsgi_script=self.wsgi_script_file)) logger.info("Activating Apache virtual host ..") assert os.system('sudo service apache2 reload') == 0
def test_robust_tables(self): column_names = ['One', 'Two', 'Three'] data = [['1', '2', '3'], ['a', 'b', 'c']] assert ansi_strip(format_robust_table(data, column_names)) == dedent(""" -------- One: 1 Two: 2 Three: 3 -------- One: a Two: b Three: c -------- """).strip() column_names = ['One', 'Two', 'Three'] data = [['1', '2', '3'], ['a', 'b', 'Here comes a\nmulti line column!']] assert ansi_strip(format_robust_table(data, column_names)) == dedent(""" ------------------ One: 1 Two: 2 Three: 3 ------------------ One: a Two: b Three: Here comes a multi line column! ------------------ """).strip()
def test_dedent(self): assert dedent('\n line 1\n line 2\n\n') == 'line 1\n line 2\n' assert dedent(''' Dedented, %s text ''', 'interpolated') == 'Dedented, interpolated text\n' assert dedent(''' Dedented, {op} text ''', op='formatted') == 'Dedented, formatted text\n'
def test_dedent(self): """Test :func:`humanfriendly.text.dedent()`.""" assert dedent('\n line 1\n line 2\n\n') == 'line 1\n line 2\n' assert dedent(''' Dedented, %s text ''', 'interpolated') == 'Dedented, interpolated text\n' assert dedent(''' Dedented, {op} text ''', op='formatted') == 'Dedented, formatted text\n'
def test_config_loader(self): """Tests for the :class:`ConfigLoader` class.""" # Test support for custom filename extensions. loader = ConfigLoader(program_name='update-dotdee', filename_extension='conf') assert '/etc/update-dotdee.conf' in loader.filename_patterns # Test loading of multiple configuration files. with MockedHomeDirectory() as directory: # Create the main user configuration file at ~/.update-dotdee.ini. main_file = os.path.join(directory, '.update-dotdee.ini') write_file(main_file, dedent(''' [main-section] main-option = value ''')) # Create some modular ~/.config/update-dotdee.d/*.ini configuration files. config_directory = os.path.join(directory, '.config', 'update-dotdee.d') os.makedirs(config_directory) modular_file_1 = os.path.join(config_directory, '1.ini') modular_file_2 = os.path.join(config_directory, '2.ini') modular_file_11 = os.path.join(config_directory, '11.ini') write_file(modular_file_1, dedent(''' [modular-section-1] my-option-name = value ''')) write_file(modular_file_2, dedent(''' [modular-section-2] my-option-name = value [main-section] modular-option = value ''')) write_file(modular_file_11, dedent(''' [modular-section-11] my-option-name = value ''')) # Use ConfigLoader to load the configuration files. loader = ConfigLoader(program_name='update-dotdee') # Make sure all configuration files were found. assert len(loader.available_files) == 4 assert loader.available_files[0] == main_file assert loader.available_files[1] == modular_file_1 assert loader.available_files[2] == modular_file_2 assert loader.available_files[3] == modular_file_11 # Make sure all configuration file sections are loaded. assert set(loader.section_names) == set([ 'main-section', 'modular-section-1', 'modular-section-2', 'modular-section-11', ]) assert loader.get_options('main-section') == { 'main-option': 'value', 'modular-option': 'value', }
def install_wsgi_app(self, python_code, *args, **kw): """ Install a temporary WSGI script file. :param python_code: A Python code template (a string). :param args: Positional arguments to be interpolated into the Python code. :param kw: Keyword arguments to be interpolated into the Python code. """ logger.info("Creating WSGI script: %s", self.wsgi_script_file) with open(self.wsgi_script_file, 'w') as handle: handle.write('%s\n' % dedent(python_code, *args, **kw)) logger.info("Creating Apache virtual host: %s", self.virtual_host_file) with open(self.virtual_host_file, 'w') as handle: netloc = self.manager.listen_addresses[0] installed_version = execute('dpkg-query', '--show', '--showformat=${Version}', 'apache2', capture=True) if NaturalOrderKey(installed_version) >= NaturalOrderKey('2.4'): root = tempfile.gettempdir() handle.write( dedent(''' <VirtualHost {netloc.address}:{netloc.port}> ServerName {server_name} WSGIScriptAlias / {wsgi_script} <Directory "{root}"> Require all granted </Directory> </VirtualHost> ''', netloc=netloc, server_name=self.name, root=root, wsgi_script=self.wsgi_script_file)) else: handle.write( dedent(''' <VirtualHost {netloc.address}:{netloc.port}> ServerName {server_name} WSGIScriptAlias / {wsgi_script} </VirtualHost> ''', netloc=netloc, server_name=self.name, wsgi_script=self.wsgi_script_file)) logger.info("Activating Apache virtual host ..") assert os.system('sudo service apache2 reload') == 0
def test_conversion_with_system_package(self): """Convert a package and map one of its requirements to a system package.""" with TemporaryDirectory() as repository_directory: with TemporaryDirectory() as distribution_directory: # Create a temporary (and rather trivial :-) Python package. with open(os.path.join(distribution_directory, 'setup.py'), 'w') as handle: handle.write( dedent(''' from setuptools import setup setup( name='system-package-conversion-test', version='1.0', install_requires=['dbus-python'], ) ''')) # Run the conversion command. converter = self.create_isolated_converter() converter.set_repository(repository_directory) converter.use_system_package('dbus-python', 'python-dbus') archives, relationships = converter.convert( [distribution_directory]) # Make sure only one archive was generated. assert len(archives) == 1 # Use deb-pkg-tools to inspect the package metadata. metadata, contents = inspect_package(archives[0]) logger.debug("Metadata of generated package: %s", dict(metadata)) logger.debug("Contents of generated package: %s", dict(contents)) # Inspect the converted package's dependency. assert metadata['Depends'].matches('python-dbus'), \ "py2deb failed to rewrite dependency name!"
def test_install_requires_version_munging(self): """ Convert a package with a requirement whose version is "munged" by pip. Refer to :func:`py2deb.converter.PackageConverter.transform_version()` for details about the purpose of this test. """ with TemporaryDirectory() as repository_directory: with TemporaryDirectory() as distribution_directory: # Create a temporary (and rather trivial :-) Python package. with open(os.path.join(distribution_directory, 'setup.py'), 'w') as handle: handle.write(dedent(''' from setuptools import setup setup( name='install-requires-munging-test', version='1.0', install_requires=['humanfriendly==1.30.0'], ) ''')) # Run the conversion command. converter = self.create_isolated_converter() converter.set_repository(repository_directory) archives, relationships = converter.convert([distribution_directory]) # Find the generated *.deb archive. pathname = find_package_archive(archives, 'python-install-requires-munging-test') # Use deb-pkg-tools to inspect the package metadata. metadata, contents = inspect_package(pathname) logger.debug("Metadata of generated package: %s", dict(metadata)) logger.debug("Contents of generated package: %s", dict(contents)) # Inspect the converted package's dependency. assert metadata['Depends'].matches('python-humanfriendly', '1.30'), \ "py2deb failed to rewrite version of dependency!" assert not metadata['Depends'].matches('python-humanfriendly', '1.30.0'), \ "py2deb failed to rewrite version of dependency!"
def test_conversion_with_configuration_file(self): """ Convert a group of packages based on the settings in a configuration file. Repeats the same test as :py:func:`test_conversion_of_isolated_packages()` but instead of using command line options the conversion process is configured using a configuration file. """ # Use a temporary directory as py2deb's repository directory so that we # can easily find the *.deb archive generated by py2deb. with TemporaryDirectory() as directory: configuration_file = os.path.join(directory, 'py2deb.ini') with open(configuration_file, 'w') as handle: handle.write(dedent(''' [py2deb] repository = {repository} name-prefix = pip-accel install-prefix = /usr/lib/pip-accel auto-install = false [alternatives] /usr/bin/pip-accel = /usr/lib/pip-accel/bin/pip-accel [package:pip-accel] no-name-prefix = true [package:coloredlogs] rename = pip-accel-coloredlogs-renamed ''', repository=directory)) # Run the conversion command. py2deb('--config=%s' % configuration_file, 'pip-accel==0.12.6') # Check the results. self.check_converted_pip_accel_packages(directory)
def test_conversion_with_configuration_file(self): """ Convert a group of packages based on the settings in a configuration file. Repeats the same test as :func:`test_conversion_of_isolated_packages()` but instead of using command line options the conversion process is configured using a configuration file. """ # Use a temporary directory as py2deb's repository directory so that we # can easily find the *.deb archive generated by py2deb. with TemporaryDirectory() as directory: configuration_file = os.path.join(directory, 'py2deb.ini') with open(configuration_file, 'w') as handle: handle.write( dedent(''' [py2deb] repository = {repository} name-prefix = pip-accel install-prefix = /usr/lib/pip-accel auto-install = false [alternatives] /usr/bin/pip-accel = /usr/lib/pip-accel/bin/pip-accel [package:pip-accel] no-name-prefix = true [package:coloredlogs] rename = pip-accel-coloredlogs-renamed ''', repository=directory)) # Run the conversion command. py2deb('--config=%s' % configuration_file, 'pip-accel==0.12.6') # Check the results. self.check_converted_pip_accel_packages(directory)
def test_render_usage(self): """Test :func:`humanfriendly.usage.render_usage()`.""" assert render_usage("Usage: some-command WITH ARGS") == "**Usage:** `some-command WITH ARGS`" assert render_usage("Supported options:") == "**Supported options:**" assert 'code-block' in render_usage(dedent(""" Here comes a shell command: $ echo test test """)) assert all(token in render_usage(dedent(""" Supported options: -n, --dry-run Don't change anything. """)) for token in ('`-n`', '`--dry-run`'))
def test_pretty_tables(self): """Test :func:`humanfriendly.tables.format_pretty_table()`.""" # The simplest case possible :-). data = [['Just one column']] assert format_pretty_table(data) == dedent(""" ------------------- | Just one column | ------------------- """).strip() # A bit more complex: two rows, three columns, varying widths. data = [['One', 'Two', 'Three'], ['1', '2', '3']] assert format_pretty_table(data) == dedent(""" --------------------- | One | Two | Three | | 1 | 2 | 3 | --------------------- """).strip() # A table including column names. column_names = ['One', 'Two', 'Three'] data = [['1', '2', '3'], ['a', 'b', 'c']] assert ansi_strip(format_pretty_table(data, column_names)) == dedent(""" --------------------- | One | Two | Three | --------------------- | 1 | 2 | 3 | | a | b | c | --------------------- """).strip() # A table that contains a column with only numeric data (will be right aligned). column_names = ['Just a label', 'Important numbers'] data = [['Row one', '15'], ['Row two', '300']] assert ansi_strip(format_pretty_table(data, column_names)) == dedent(""" ------------------------------------ | Just a label | Important numbers | ------------------------------------ | Row one | 15 | | Row two | 300 | ------------------------------------ """).strip()
def install_wsgi_app(self, python_code, *args, **kw): """ Install a temporary WSGI script file. :param python_code: A Python code template (a string). :param args: Positional arguments to be interpolated into the Python code. :param kw: Keyword arguments to be interpolated into the Python code. """ logger.info("Creating WSGI script: %s", self.wsgi_script_file) with open(self.wsgi_script_file, 'w') as handle: handle.write('%s\n' % dedent(python_code, *args, **kw)) logger.info("Creating Apache virtual host: %s", self.virtual_host_file) with open(self.virtual_host_file, 'w') as handle: netloc = self.manager.listen_addresses[0] handle.write(dedent(''' <VirtualHost {netloc.address}:{netloc.port}> ServerName {server_name} WSGIScriptAlias / {wsgi_script} </VirtualHost> ''', netloc=netloc, server_name=self.name, wsgi_script=self.wsgi_script_file)) logger.info("Activating Apache virtual host ..") assert os.system('sudo service apache2 reload') == 0
def test_install_requires_version_munging(self): """ Convert a package with a requirement whose version is "munged" by pip. Refer to :func:`py2deb.converter.PackageConverter.transform_version()` for details about the purpose of this test. """ with TemporaryDirectory() as repository_directory: with TemporaryDirectory() as distribution_directory: # Create a temporary (and rather trivial :-) Python package. with open(os.path.join(distribution_directory, 'setup.py'), 'w') as handle: handle.write( dedent(''' from setuptools import setup setup( name='install-requires-munging-test', version='1.0', install_requires=['humanfriendly==1.30.0'], ) ''')) # Run the conversion command. converter = self.create_isolated_converter() converter.set_repository(repository_directory) archives, relationships = converter.convert( [distribution_directory]) # Find the generated *.deb archive. pathname = find_package_archive( archives, 'python-install-requires-munging-test') # Use deb-pkg-tools to inspect the package metadata. metadata, contents = inspect_package(pathname) logger.debug("Metadata of generated package: %s", dict(metadata)) logger.debug("Contents of generated package: %s", dict(contents)) # Inspect the converted package's dependency. assert metadata['Depends'].matches('python-humanfriendly', '1.30'), \ "py2deb failed to rewrite version of dependency!" assert not metadata['Depends'].matches('python-humanfriendly', '1.30.0'), \ "py2deb failed to rewrite version of dependency!"
def test_cli(self): """Test the command line interface.""" # Test that the usage message is printed by default. returncode, output = main() assert 'Usage:' in output # Test that the usage message can be requested explicitly. returncode, output = main('--help') assert 'Usage:' in output # Test handling of invalid command line options. returncode, output = main('--unsupported-option') assert returncode != 0 # Test `humanfriendly --format-number'. returncode, output = main('--format-number=1234567') assert output.strip() == '1,234,567' # Test `humanfriendly --format-size'. random_byte_count = random.randint(1024, 1024 * 1024) returncode, output = main('--format-size=%i' % random_byte_count) assert output.strip() == humanfriendly.format_size(random_byte_count) # Test `humanfriendly --format-table'. returncode, output = main('--format-table', '--delimiter=\t', input='1\t2\t3\n4\t5\t6\n7\t8\t9') assert output.strip() == dedent(''' ------------- | 1 | 2 | 3 | | 4 | 5 | 6 | | 7 | 8 | 9 | ------------- ''').strip() # Test `humanfriendly --format-timespan'. random_timespan = random.randint(5, 600) returncode, output = main('--format-timespan=%i' % random_timespan) assert output.strip() == humanfriendly.format_timespan(random_timespan) # Test `humanfriendly --parse-size'. returncode, output = main('--parse-size=5 KB') assert int(output) == humanfriendly.parse_size('5 KB') # Test `humanfriendly --run-command'. returncode, output = main('--run-command', 'bash', '-c', 'sleep 2 && exit 42') assert returncode == 42
def preprocess_parse_result(self, text): """Ignore leading/trailing whitespace in usage parsing tests.""" return tuple([p.strip() for p in r] for r in parse_usage(dedent(text)))