From ab31f26d61f7b4b79d30d135048dfc8bf6fbb4423cd8e3f7796de4ef62f84666 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Wed, 29 Jul 2020 12:49:19 +0000 Subject: [PATCH] Accepting request 822791 from home:sebix:branches:devel:languages:python - remove patches not necessary anymore: - magic-new-mime.patch - magic-pep8.patch - magic-tests.patch - magic-new-file.patch - add patch fix-test.patch and fix-test-tumbleweed.patch to adapt the `file` test outputs to OpenSUSE. - update to version 0.4.18: - Make bindings for magic_[set|get]param optional, and throw NotImplementedError if they are used but not supported. Only call setparam() in the constructor if it's supported. This prevents breakage on CentOS7 which uses an old version of libmagic. - update to version 0.4.16 and 0.4.17 (changelog is combined upstream): - add MAGIC_MIME_TYPE constant, use that in preference to MAGIC_MIME internally. This sets up for a breaking change in a future major version bump where MAGIC_MIME will change to mathch magic.h. - add magic.version() function to return library version - add setparam/getparam to control internal behavior - increase internal limits with setparam to prevent spurious error on some jpeg files - various setup.py improvements to declare modern python support - support MSYS2 magic dlls - fix warning about using 'is' on an int in python 3.8 - include tests in source distribution - many test improvements: - tox runner support - remove deprecated test_suite field from setup.py - docker tests that cover all LTS ubuntu versions - add test for snapp file identification - doc improvements - document dependency install process for debian - various typos OBS-URL: https://build.opensuse.org/request/show/822791 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-python-magic?expand=0&rev=13 --- 0.4.15.tar.gz | 3 - 0.4.18.tar.gz | 3 + fix-test-tumbleweed.patch | 34 ++++++ fix-test.patch | 13 +++ magic-new-file.patch | 69 ------------ magic-new-mime.patch | 52 --------- magic-pep8.patch | 207 ------------------------------------ magic-tests.patch | 22 ---- python-python-magic.changes | 35 ++++++ python-python-magic.spec | 26 +++-- 10 files changed, 101 insertions(+), 363 deletions(-) delete mode 100644 0.4.15.tar.gz create mode 100644 0.4.18.tar.gz create mode 100644 fix-test-tumbleweed.patch create mode 100644 fix-test.patch delete mode 100644 magic-new-file.patch delete mode 100644 magic-new-mime.patch delete mode 100644 magic-pep8.patch delete mode 100644 magic-tests.patch diff --git a/0.4.15.tar.gz b/0.4.15.tar.gz deleted file mode 100644 index 3368d05..0000000 --- a/0.4.15.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d730389249ab1e34ffb0a3c5beaa44e116687ffa081e0176dab6c59ff271593 -size 75476 diff --git a/0.4.18.tar.gz b/0.4.18.tar.gz new file mode 100644 index 0000000..ef3283e --- /dev/null +++ b/0.4.18.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b787e8056c115f37e2af11e0b98dc67d5fc182ed5ed827a62f95e3a7f0ed4be4 +size 856291 diff --git a/fix-test-tumbleweed.patch b/fix-test-tumbleweed.patch new file mode 100644 index 0000000..c0d5dd4 --- /dev/null +++ b/fix-test-tumbleweed.patch @@ -0,0 +1,34 @@ +--- python-magic-0.4.18/test/test.py 2020-05-06 04:25:46.000000000 +0200 ++++ python-magic-0.4.18/test/test.py 2020-07-25 19:51:08.263172240 +0200 +@@ -59,9 +59,9 @@ + def test_from_buffer_str_and_bytes(self): + m = magic.Magic(mime=True) + s = '#!/usr/bin/env python\nprint("foo")' +- self.assertEqual("text/x-python", m.from_buffer(s)) ++ self.assertEqual("text/x-script.python", m.from_buffer(s)) + b = b'#!/usr/bin/env python\nprint("foo")' +- self.assertEqual("text/x-python", m.from_buffer(b)) ++ self.assertEqual("text/x-script.python", m.from_buffer(b)) + + def test_mime_types(self): + dest = os.path.join(MagicTest.TESTDATA_DIR, +@@ -70,7 +70,7 @@ + try: + m = magic.Magic(mime=True) + self.assert_values(m, { +- 'magic._pyc_': 'application/octet-stream', ++ 'magic._pyc_': 'text/x-bytecode.python', + 'test.pdf': 'application/pdf', + 'test.gz': ('application/gzip', 'application/x-gzip'), + 'test.snappy.parquet': 'application/octet-stream', +@@ -97,7 +97,9 @@ + ': Sun Jun 29 01:32:52 2008, from Unix, original size 15', + 'gzip compressed data, was "test", ' + 'last modified: Sun Jun 29 01:32:52 2008, ' +- 'from Unix, original size modulo 2^32 15' ++ 'from Unix, original size modulo 2^32 15', ++ 'gzip compressed data, was "test", last modified: ' ++ 'Sun Jun 29 01:32:52 2008, from Unix, truncated', + ), + 'text.txt': 'ASCII text', + 'test.snappy.parquet': ('Apache Parquet', 'Par archive data'), diff --git a/fix-test.patch b/fix-test.patch new file mode 100644 index 0000000..64d5908 --- /dev/null +++ b/fix-test.patch @@ -0,0 +1,13 @@ +--- python-magic-0.4.18/test/test.py 2020-05-06 04:25:46.000000000 +0200 ++++ python-magic-0.4.18/test/test.py 2020-07-25 20:02:37.988452945 +0200 +@@ -97,7 +97,9 @@ + ': Sun Jun 29 01:32:52 2008, from Unix, original size 15', + 'gzip compressed data, was "test", ' + 'last modified: Sun Jun 29 01:32:52 2008, ' +- 'from Unix, original size modulo 2^32 15' ++ 'from Unix, original size modulo 2^32 15', ++ 'gzip compressed data, was "test", last modified: ' ++ 'Sun Jun 29 01:32:52 2008, from Unix, truncated', + ), + 'text.txt': 'ASCII text', + 'test.snappy.parquet': ('Apache Parquet', 'Par archive data'), diff --git a/magic-new-file.patch b/magic-new-file.patch deleted file mode 100644 index 3fc7753..0000000 --- a/magic-new-file.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 93492a12aa8ae55e62bce0472e92800eac4b6269 Mon Sep 17 00:00:00 2001 -From: Louis Sautier -Date: Tue, 14 Aug 2018 11:14:19 +0200 -Subject: [PATCH] Tests: allow differences when reading a buffer or a file, - fixes #173 - -Also remove the loop in order to avoid analyzing files or buffers for each -expected value, replace it with a call to assertIn(). ---- - test/test.py | 25 ++++++++++++++----------- - 1 file changed, 14 insertions(+), 11 deletions(-) - -Index: python-magic-0.4.15/test/test.py -=================================================================== ---- python-magic-0.4.15.orig/test/test.py -+++ python-magic-0.4.15/test/test.py -@@ -11,7 +11,7 @@ import magic - class MagicTest(unittest.TestCase): - TESTDATA_DIR = os.path.join(os.path.dirname(__file__), 'testdata') - -- def assert_values(self, m, expected_values): -+ def assert_values(self, m, expected_values, buf_equals_file=True): - for filename, expected_value in expected_values.items(): - try: - filename = os.path.join(self.TESTDATA_DIR, filename) -@@ -22,15 +22,16 @@ class MagicTest(unittest.TestCase): - if type(expected_value) is not tuple: - expected_value = (expected_value,) - -- for i in expected_value: -- with open(filename, 'rb') as f: -- buf_value = m.from_buffer(f.read()) -- -- file_value = m.from_file(filename) -- if buf_value == i and file_value == i: -- break -- else: -- self.assertTrue(False, "no match for " + repr(expected_value)) -+ with open(filename, 'rb') as f: -+ buf_value = m.from_buffer(f.read()) -+ -+ file_value = m.from_file(filename) -+ -+ if buf_equals_file: -+ self.assertEqual(buf_value, file_value) -+ -+ for value in (buf_value, file_value): -+ self.assertIn(value, expected_value) - - def test_from_buffer_str_and_bytes(self): - m = magic.Magic(mime=True) -@@ -64,12 +65,12 @@ class MagicTest(unittest.TestCase): - 'magic._pyc_': 'python 2.4 byte-compiled', - 'test.pdf': 'PDF document, version 1.2', - 'test.gz': -- ('gzip compressed data, was "test", from Unix, last ' -- 'modified: Sun Jun 29 01:32:52 2008', -- 'gzip compressed data, was "test", last modified' -- ': Sun Jun 29 01:32:52 2008, from Unix'), -+ ('gzip compressed data, was "test", from Unix, last modified: Sun Jun 29 01:32:52 2008', -+ 'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix', -+ 'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size 15', -+ 'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size modulo 2^32 15'), - 'text.txt': 'ASCII text', -- }) -+ }, buf_equals_file=False) - finally: - del os.environ['TZ'] - diff --git a/magic-new-mime.patch b/magic-new-mime.patch deleted file mode 100644 index c03a6a2..0000000 --- a/magic-new-mime.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 4bda684f8b461cc1f69593799efcf6afe8397756 Mon Sep 17 00:00:00 2001 -From: Adam Hupp -Date: Sat, 9 Dec 2017 09:09:00 -0800 -Subject: [PATCH] fix test for xenial since travis started enabling it - ---- - test/test.py | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/test/test.py b/test/test.py -index addccc6..c6e2d9c 100755 ---- a/test/test.py -+++ b/test/test.py -@@ -17,7 +17,7 @@ def assert_values(self, m, expected_values): - except TypeError: - filename = os.path.join(self.TESTDATA_DIR.encode('utf-8'), filename) - -- -+ - if type(expected_value) is not tuple: - expected_value = (expected_value,) - -@@ -37,7 +37,7 @@ def test_from_buffer_str_and_bytes(self): - self.assertEqual("text/x-python", m.from_buffer(s)) - b = b'#!/usr/bin/env python\nprint("foo")' - self.assertEqual("text/x-python", m.from_buffer(b)) -- -+ - def test_mime_types(self): - dest = os.path.join(MagicTest.TESTDATA_DIR, b'\xce\xbb'.decode('utf-8')) - shutil.copyfile(os.path.join(MagicTest.TESTDATA_DIR, 'lambda'), dest) -@@ -92,9 +92,9 @@ def test_keep_going(self): - - m = magic.Magic(mime=True) - self.assertEqual(m.from_file(filename), 'image/jpeg') -- -+ - m = magic.Magic(mime=True, keep_going=True) -- self.assertEqual(m.from_file(filename), 'image/jpeg') -+ self.assertEqual(m.from_file(filename), 'image/jpeg\\012- application/octet-stream') - - - def test_rethrow(self): -@@ -103,7 +103,7 @@ def test_rethrow(self): - def t(x,y): - raise magic.MagicException("passthrough") - magic.magic_buffer = t -- -+ - self.assertRaises(magic.MagicException, magic.from_buffer, "hello", True) - finally: - magic.magic_buffer = old diff --git a/magic-pep8.patch b/magic-pep8.patch deleted file mode 100644 index 32371a2..0000000 --- a/magic-pep8.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 828ff0289642a95ec00fe4f9a55da51c455277c8 Mon Sep 17 00:00:00 2001 -From: "Guido A.J. Stevens" -Date: Thu, 25 Jan 2018 08:29:18 +0000 -Subject: [PATCH] PEP8 - ---- - magic.py | 30 ++++++++++++++++-------------- - test/test.py | 29 ++++++++++++++++++----------- - 2 files changed, 34 insertions(+), 25 deletions(-) - -diff --git a/magic.py b/magic.py -index dd86389..83b906d 100644 ---- a/magic.py -+++ b/magic.py -@@ -19,7 +19,6 @@ - - import sys - import glob --import os.path - import ctypes - import ctypes.util - import threading -@@ -63,7 +62,7 @@ def __init__(self, mime=False, magic_file=None, mime_encoding=False, - - self.cookie = magic_open(self.flags) - self.lock = threading.Lock() -- -+ - magic_load(self.cookie, magic_file) - - def from_buffer(self, buf): -@@ -76,7 +75,7 @@ def from_buffer(self, buf): - # otherwise this string is passed as wchar* - # which is not what libmagic expects - if type(buf) == str and str != bytes: -- buf = buf.encode('utf-8', errors='replace') -+ buf = buf.encode('utf-8', errors='replace') - return maybe_decode(magic_buffer(self.cookie, buf)) - except MagicException as e: - return self._handle509Bug(e) -@@ -99,7 +98,7 @@ def _handle509Bug(self, e): - return "application/octet-stream" - else: - raise e -- -+ - def __del__(self): - # no _thread_check here because there can be no other - # references to this object at this point. -@@ -117,12 +116,14 @@ def __del__(self): - - _instances = {} - -+ - def _get_magic_type(mime): - i = _instances.get(mime) - if i is None: - i = _instances[mime] = Magic(mime=mime) - return i - -+ - def from_file(filename, mime=False): - """" - Accepts a filename and returns the detected filetype. Return -@@ -135,6 +136,7 @@ def from_file(filename, mime=False): - m = _get_magic_type(mime) - return m.from_file(filename) - -+ - def from_buffer(buffer, mime=False): - """ - Accepts a binary string and returns the detected filetype. Return -@@ -148,25 +150,25 @@ def from_buffer(buffer, mime=False): - return m.from_buffer(buffer) - - -- -- - libmagic = None - # Let's try to find magic or magic1 --dll = ctypes.util.find_library('magic') or ctypes.util.find_library('magic1') or ctypes.util.find_library('cygmagic-1') -+dll = ctypes.util.find_library('magic') \ -+ or ctypes.util.find_library('magic1') \ -+ or ctypes.util.find_library('cygmagic-1') - --# This is necessary because find_library returns None if it doesn't find the library -+# necessary because find_library returns None if it doesn't find the library - if dll: - libmagic = ctypes.CDLL(dll) - - if not libmagic or not libmagic._name: -- windows_dlls = ['magic1.dll','cygmagic-1.dll'] -+ windows_dlls = ['magic1.dll', 'cygmagic-1.dll'] - platform_to_lib = {'darwin': ['/opt/local/lib/libmagic.dylib', - '/usr/local/lib/libmagic.dylib'] + -- # Assumes there will only be one version installed -- glob.glob('/usr/local/Cellar/libmagic/*/lib/libmagic.dylib'), -+ # Assumes there will only be one version installed -+ glob.glob('/usr/local/Cellar/libmagic/*/lib/libmagic.dylib'), # flake8:noqa - 'win32': windows_dlls, - 'cygwin': windows_dlls, -- 'linux': ['libmagic.so.1'], # fallback for some Linuxes (e.g. Alpine) where library search does not work -+ 'linux': ['libmagic.so.1'], # fallback for some Linuxes (e.g. Alpine) where library search does not work # flake8:noqa - } - platform = 'linux' if sys.platform.startswith('linux') else sys.platform - for dll in platform_to_lib.get(platform, []): -@@ -204,13 +206,13 @@ def maybe_decode(s): - return s - else: - return s.decode('utf-8') -- -+ - def coerce_filename(filename): - if filename is None: - return None - - # ctypes will implicitly convert unicode strings to bytes with -- # .encode('ascii'). If you use the filesystem encoding -+ # .encode('ascii'). If you use the filesystem encoding - # then you'll get inconsistent behavior (crashes) depending on the user's - # LANG environment variable - is_unicode = (sys.version_info[0] <= 2 and -diff --git a/test/test.py b/test/test.py -index c6e2d9c..a92972b 100755 ---- a/test/test.py -+++ b/test/test.py -@@ -1,4 +1,4 @@ --import os, sys -+import os - # for output which reports a local time - os.environ['TZ'] = 'GMT' - import shutil -@@ -7,6 +7,7 @@ - - import magic - -+ - class MagicTest(unittest.TestCase): - TESTDATA_DIR = os.path.join(os.path.dirname(__file__), 'testdata') - -@@ -15,8 +16,8 @@ def assert_values(self, m, expected_values): - try: - filename = os.path.join(self.TESTDATA_DIR, filename) - except TypeError: -- filename = os.path.join(self.TESTDATA_DIR.encode('utf-8'), filename) -- -+ filename = os.path.join( -+ self.TESTDATA_DIR.encode('utf-8'), filename) - - if type(expected_value) is not tuple: - expected_value = (expected_value,) -@@ -39,7 +40,8 @@ def test_from_buffer_str_and_bytes(self): - self.assertEqual("text/x-python", m.from_buffer(b)) - - def test_mime_types(self): -- dest = os.path.join(MagicTest.TESTDATA_DIR, b'\xce\xbb'.decode('utf-8')) -+ dest = os.path.join(MagicTest.TESTDATA_DIR, -+ b'\xce\xbb'.decode('utf-8')) - shutil.copyfile(os.path.join(MagicTest.TESTDATA_DIR, 'lambda'), dest) - try: - m = magic.Magic(mime=True) -@@ -56,14 +58,16 @@ def test_mime_types(self): - - def test_descriptions(self): - m = magic.Magic() -- os.environ['TZ'] = 'UTC' # To get the last modified date of test.gz in UTC -+ os.environ['TZ'] = 'UTC' # To get last modified date of test.gz in UTC - try: - self.assert_values(m, { - 'magic._pyc_': 'python 2.4 byte-compiled', - 'test.pdf': 'PDF document, version 1.2', - 'test.gz': -- ('gzip compressed data, was "test", from Unix, last modified: Sun Jun 29 01:32:52 2008', -- 'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix'), -+ ('gzip compressed data, was "test", from Unix, last ' -+ 'modified: Sun Jun 29 01:32:52 2008', -+ 'gzip compressed data, was "test", last modified' -+ ': Sun Jun 29 01:32:52 2008, from Unix'), - 'text.txt': 'ASCII text', - }) - finally: -@@ -94,18 +98,21 @@ def test_keep_going(self): - self.assertEqual(m.from_file(filename), 'image/jpeg') - - m = magic.Magic(mime=True, keep_going=True) -- self.assertEqual(m.from_file(filename), 'image/jpeg\\012- application/octet-stream') -- -+ self.assertEqual(m.from_file(filename), -+ 'image/jpeg\\012- application/octet-stream') - - def test_rethrow(self): - old = magic.magic_buffer - try: -- def t(x,y): -+ def t(x, y): - raise magic.MagicException("passthrough") - magic.magic_buffer = t - -- self.assertRaises(magic.MagicException, magic.from_buffer, "hello", True) -+ with self.assertRaises(magic.MagicException): -+ magic.from_buffer("hello", True) - finally: - magic.magic_buffer = old -+ -+ - if __name__ == '__main__': - unittest.main() diff --git a/magic-tests.patch b/magic-tests.patch deleted file mode 100644 index 6c08b95..0000000 --- a/magic-tests.patch +++ /dev/null @@ -1,22 +0,0 @@ -From e83487a20bacd4f9b33d0478861671bf79468f59 Mon Sep 17 00:00:00 2001 -From: Louis Sautier -Date: Mon, 13 Aug 2018 12:15:13 +0200 -Subject: [PATCH] Allow x-gzip as MIME type for gzip files, fixes #96 - ---- - test/test.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/test/test.py b/test/test.py -index e29335f..e3ee703 100755 ---- a/test/test.py -+++ b/test/test.py -@@ -54,7 +54,7 @@ def test_mime_types(self): - self.assert_values(m, { - 'magic._pyc_': 'application/octet-stream', - 'test.pdf': 'application/pdf', -- 'test.gz': 'application/gzip', -+ 'test.gz': ('application/gzip', 'application/x-gzip'), - 'text.txt': 'text/plain', - b'\xce\xbb'.decode('utf-8'): 'text/plain', - b'\xce\xbb': 'text/plain', diff --git a/python-python-magic.changes b/python-python-magic.changes index 6af38bb..fd721f8 100644 --- a/python-python-magic.changes +++ b/python-python-magic.changes @@ -1,3 +1,38 @@ +------------------------------------------------------------------- +Sat Jul 25 14:46:39 UTC 2020 - Sebastian Wagner + +- remove patches not necessary anymore: + - magic-new-mime.patch + - magic-pep8.patch + - magic-tests.patch + - magic-new-file.patch +- add patch fix-test.patch and fix-test-tumbleweed.patch to adapt the `file` test outputs to OpenSUSE. +- update to version 0.4.18: + - Make bindings for magic_[set|get]param optional, and throw NotImplementedError + if they are used but not supported. Only call setparam() in the constructor if + it's supported. This prevents breakage on CentOS7 which uses an old version of + libmagic. +- update to version 0.4.16 and 0.4.17 (changelog is combined upstream): + - add MAGIC_MIME_TYPE constant, use that in preference to MAGIC_MIME internally. + This sets up for a breaking change in a future major version bump where + MAGIC_MIME will change to mathch magic.h. + - add magic.version() function to return library version + - add setparam/getparam to control internal behavior + - increase internal limits with setparam to prevent spurious error on some jpeg files + - various setup.py improvements to declare modern python support + - support MSYS2 magic dlls + - fix warning about using 'is' on an int in python 3.8 + - include tests in source distribution + - many test improvements: + - tox runner support + - remove deprecated test_suite field from setup.py + - docker tests that cover all LTS ubuntu versions + - add test for snapp file identification + - doc improvements + - document dependency install process for debian + - various typos + - document test running process + ------------------------------------------------------------------- Thu Jul 4 12:09:23 UTC 2019 - Tomáš Chvátal diff --git a/python-python-magic.spec b/python-python-magic.spec index 69d60cf..6a0d4d8 100644 --- a/python-python-magic.spec +++ b/python-python-magic.spec @@ -1,7 +1,7 @@ # # spec file for package python-python-magic # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,17 +19,16 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define oldpython python Name: python-python-magic -Version: 0.4.15 +Version: 0.4.18 Release: 0 Summary: File type identification using libmagic License: Python-2.0 Group: Development/Languages/Python URL: https://github.com/ahupp/python-magic Source: https://github.com/ahupp/python-magic/archive/%{version}.tar.gz -Patch0: magic-new-mime.patch -Patch1: magic-pep8.patch -Patch2: magic-tests.patch -Patch3: magic-new-file.patch +#PATCH-FIX-OPENSUSE fix-test.patch -- adapt file outputs to opensuse +Patch0: fix-test.patch +Patch1: fix-test-tumbleweed.patch BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: file @@ -47,12 +46,18 @@ Conflicts: %{oldpython}-magic %description This module uses ctypes to access the libmagic file type -identification library. It makes use of the local magic database and +identification library. It makes use of the local magic database and supports both textual and MIME-type output. %prep %setup -q -n python-magic-%{version} -%autopatch -p1 +%if 0%{?suse_version} > 1500 +# Tumbleweed +%patch1 -p1 +%elif 0%{?sle_version} < 150300 && 0%{?is_opensuse} +# Leap 15.2 and older +%patch0 -p1 +%endif %build %python_build @@ -62,11 +67,12 @@ supports both textual and MIME-type output. %python_expand %fdupes %{buildroot}%{$python_sitelib} %check -export LANG=en_US.UTF-8 -%python_exec setup.py test +export LC_ALL=en_US.UTF-8 +%python_expand PYTHONPATH=. $python test/test.py %files %{python_files} %license LICENSE +%doc README.md %{python_sitelib}/magic.py* %pycache_only %{python_sitelib}/__pycache__/magic*.py* %{python_sitelib}/python_magic-%{version}-py*.egg-info