Repository: pylint-dev/pylint

Issue:
Use "symilar -d args" error
### Bug description

```python
In fedora38

cat > test.py << EOF
#!/usr/bin/env python3

print('test')
EOF

symilar -d 4 test.py test.py
```

### Command used

```shell
symilar.py
```


### Pylint output

```python
[root@e6aaae57a5ab ~]# symilar -d 4 test.py test.py
Traceback (most recent call last):
  File "/usr/bin/symilar", line 8, in <module>
    sys.exit(run_symilar())
             ^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pylint/__init__.py", line 84, in run_symilar
    SimilarRun(argv or sys.argv[1:])
  File "/usr/lib/python3.11/site-packages/pylint/checkers/similar.py", line 931, in Run
    min_lines = int(val)
                ^^^^^^^^
ValueError: invalid literal for int() with base 10: ''
```


### Expected behavior
```
[root@e6aaae57a5ab ~]# symilar --duplicates 4 test.py test.py
TOTAL lines=6 duplicates=0 percent=0.00
```
### Pylint version

```shell
pylint 2.17.4
astroid 2.15.4
python 3.11.5
```



Discussion:

Patch:
diff --git a/doc/whatsnew/fragments/9343.bugfix b/doc/whatsnew/fragments/9343.bugfix
new file mode 100644
index 0000000000..0a3a620809
--- /dev/null
+++ b/doc/whatsnew/fragments/9343.bugfix
@@ -0,0 +1,4 @@
+Fixed a crash in ``symilar`` when the ``-d`` or ``-i`` short option were not properly recognized.
+It's still impossible to do ``-d=1`` (you must do ``-d 1``).
+
+Closes #9343
diff --git a/pylint/checkers/similar.py b/pylint/checkers/similar.py
index cfe649b180..ada141da36 100644
--- a/pylint/checkers/similar.py
+++ b/pylint/checkers/similar.py
@@ -39,7 +39,7 @@
 import warnings
 from collections import defaultdict
 from collections.abc import Callable, Generator, Iterable, Sequence
-from getopt import getopt
+from getopt import GetoptError, getopt
 from io import BufferedIOBase, BufferedReader, BytesIO
 from itertools import chain
 from typing import (
@@ -906,7 +906,7 @@ def Run(argv: Sequence[str] | None = None) -> NoReturn:
     if argv is None:
         argv = sys.argv[1:]
 
-    s_opts = "hdi"
+    s_opts = "hd:i:"
     l_opts = [
         "help",
         "duplicates=",
@@ -920,10 +920,18 @@ def Run(argv: Sequence[str] | None = None) -> NoReturn:
     ignore_docstrings = False
     ignore_imports = False
     ignore_signatures = False
-    opts, args = getopt(list(argv), s_opts, l_opts)
+    try:
+        opts, args = getopt(list(argv), s_opts, l_opts)
+    except GetoptError as e:
+        print(e)
+        usage(2)
     for opt, val in opts:
         if opt in {"-d", "--duplicates"}:
-            min_lines = int(val)
+            try:
+                min_lines = int(val)
+            except ValueError as e:
+                print(e)
+                usage(2)
         elif opt in {"-h", "--help"}:
             usage()
         elif opt in {"-i", "--ignore-comments"}:


Test patch:
diff --git a/tests/checkers/unittest_similar.py b/tests/checkers/unittest_symilar.py
similarity index 92%
rename from tests/checkers/unittest_similar.py
rename to tests/checkers/unittest_symilar.py
index 8c00faee54..91a9e5e545 100644
--- a/tests/checkers/unittest_similar.py
+++ b/tests/checkers/unittest_symilar.py
@@ -497,3 +497,32 @@ def test_set_duplicate_lines_to_zero() -> None:
         similar.Run(["--duplicates=0", SIMILAR1, SIMILAR2])
     assert ex.value.code == 0
     assert output.getvalue() == ""
+
+
+@pytest.mark.parametrize("v", ["d"])
+def test_bad_equal_short_form_option(v: str) -> None:
+    """Regression test for https://github.com/pylint-dev/pylint/issues/9343"""
+    output = StringIO()
+    with redirect_stdout(output), pytest.raises(SystemExit) as ex:
+        similar.Run([f"-{v}=0", SIMILAR1, SIMILAR2])
+    assert ex.value.code == 2
+    assert "invalid literal for int() with base 10: '=0'" in output.getvalue()
+
+
+@pytest.mark.parametrize("v", ["i", "d"])
+def test_space_short_form_option(v: str) -> None:
+    """Regression test for https://github.com/pylint-dev/pylint/issues/9343"""
+    output = StringIO()
+    with redirect_stdout(output), pytest.raises(SystemExit) as ex:
+        similar.Run([f"-{v} 2", SIMILAR1, SIMILAR2])
+    assert ex.value.code == 0
+    assert "similar lines in" in output.getvalue()
+
+
+def test_bad_short_form_option() -> None:
+    """Regression test for https://github.com/pylint-dev/pylint/issues/9343"""
+    output = StringIO()
+    with redirect_stdout(output), pytest.raises(SystemExit) as ex:
+        similar.Run(["-j=0", SIMILAR1, SIMILAR2])
+    assert ex.value.code == 2
+    assert "option -j not recognized" in output.getvalue()