Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE][DOC] Add (minimal) CLI #102

Merged
merged 1 commit into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The version is represented by three digits: a.b.c.

## Unreleased

FEATURE:
- `cli`: add (minimal) command line interface

## \[0.1.1\] - 2024-06-10

Expand Down
75 changes: 69 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,34 @@ Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change, and give a look to the
[contribution guidelines](https://github.com/VascoSch92/symmetria/blob/main/CONTRIBUTING.md).

---

- [Installation](#installation)
- [Quickstart](#quickstart)
- [Command Line Interface](#command-line-interface)
- [Overview](#overview)

---
## Installation

Symmetria can be comfortably installed from PyPI using the command

```bash
pip install symmetria
```text
$ pip install symmetria
```

or directly from the source GitHub code with

```bash
pip install git+https://github.com/VascoSch92/symmetria@xxx
```text
$ pip install git+https://github.com/VascoSch92/symmetria@xxx
```

where `xxx` is the name of the branch or the tag you would like to install.

You can check that `symmetria` was successfully installed by typing the command

```bash
symmetria --version
```text
$ symmetria --version
```

## Quickstart
Expand Down Expand Up @@ -171,6 +179,61 @@ in a nice formatted table:
Click [here](https://symmetria.readthedocs.io/en/latest/pages/API_reference/elements/index.html) for an overview of
all the functionalities implemented in `symmetria`.


## Command Line Interface
Symmetria also provides a simple command line interface to find all what you need just with a line.

```text
$ symmetria 132
+------------------------------------------------------+
| Permutation(1, 3, 2) |
+------------------------------------------------------+
| order | 2 |
+---------------------------+--------------------------+
| degree | 3 |
+---------------------------+--------------------------+
| is derangement | False |
+---------------------------+--------------------------+
| inverse | (1, 3, 2) |
+---------------------------+--------------------------+
| parity | -1 (odd) |
+---------------------------+--------------------------+
| cycle notation | (1)(2 3) |
+---------------------------+--------------------------+
| cycle type | (1, 2) |
+---------------------------+--------------------------+
| inversions | [(2, 3)] |
+---------------------------+--------------------------+
| ascents | [1] |
+---------------------------+--------------------------+
| descents | [2] |
+---------------------------+--------------------------+
| excedencees | [2] |
+---------------------------+--------------------------+
| records | [1, 2] |
+---------------------------+--------------------------+
```

Check it out.

```text
$ symmetria --help
Symmetria, an intuitive framework for working with the symmetric group and its elements.


Usage: symmetria <ARGUMENT> [OPTIONS]

Options:
-h, --help Print help
-v, --version Print version

Argument (optional):
permutation A permutation you want to learn more about.
The permutation must be given in its one-line format, i.e.,
for the permutation Permutation(2, 3, 1), write 231.
```


## Overview

| **Statistics** | ![Static Badge](https://img.shields.io/badge/symmetria-blue?style=for-the-badge) |
Expand Down
11 changes: 9 additions & 2 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,33 @@ with the symmetric group and its elements.


.. toctree::
:hidden:
:maxdepth: 1
:caption: Getting started
:hidden:

pages/getting_started/installation
pages/getting_started/quickstart


.. toctree::
:hidden:
:maxdepth: 2
:caption: API references
:hidden:

pages/API_reference/elements/index
pages/API_reference/groups/index
pages/API_reference/generators/index

.. toctree::
:hidden:
:maxdepth: 1
:caption: Command Line Interface

pages/cli/command_line_interface

.. toctree::
:hidden:
:maxdepth: 1
:caption: Community

pages/community/contributing.md
Expand Down
56 changes: 56 additions & 0 deletions docs/source/pages/cli/command_line_interface.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Command Line Interface
======================

Symmetria also provides a simple command line interface to find all what you need just with a line.

.. code-block:: text

$ symmetria 132

+------------------------------------------------------+
| Permutation(1, 3, 2) |
+------------------------------------------------------+
| order | 2 |
+---------------------------+--------------------------+
| degree | 3 |
+---------------------------+--------------------------+
| is derangement | False |
+---------------------------+--------------------------+
| inverse | (1, 3, 2) |
+---------------------------+--------------------------+
| parity | -1 (odd) |
+---------------------------+--------------------------+
| cycle notation | (1)(2 3) |
+---------------------------+--------------------------+
| cycle type | (1, 2) |
+---------------------------+--------------------------+
| inversions | [(2, 3)] |
+---------------------------+--------------------------+
| ascents | [1] |
+---------------------------+--------------------------+
| descents | [2] |
+---------------------------+--------------------------+
| excedencees | [2] |
+---------------------------+--------------------------+
| records | [1, 2] |
+---------------------------+--------------------------+

Check it out.

.. code-block:: text

$ symmetria --help

Symmetria, an intuitive framework for working with the symmetric group and its elements.


Usage: symmetria <ARGUMENT> [OPTIONS]

Options:
-h, --help Print help
-v, --version Print version

Argument (optional):
permutation A permutation you want to learn more about.
The permutation must be given in its one-line format, i.e.,
for the permutation Permutation(2, 3, 1), write 231.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ requires = ["setuptools>61", "wheel", "toml", "build"]
build-backend = "setuptools.build_meta"

[project.scripts]
symmetria = "symmetria:_log_version"
symmetria = "symmetria.__main__:main"

[tool.pytest.ini_options]
cache_dir = "tests/.cache/pytest"
Expand Down
20 changes: 0 additions & 20 deletions symmetria/__init__.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,7 @@
import sys

from symmetria.elements.cycle import Cycle
from symmetria.generators.api import generate
from symmetria.elements.permutation import Permutation
from symmetria.elements.cycle_decomposition import CycleDecomposition

__version__ = "0.1.1"
__all__ = ["__version__", "generate", "Permutation", "Cycle", "CycleDecomposition"]


def _log_version() -> None:
"""Private method which take a command line argument and log the version of `symmetria`."""
if len(sys.argv) == 0 or len(sys.argv) == 1:
raise Exception("No command provided.")
elif len(sys.argv) == 2:
if sys.argv[1] == "--version":
print(f"v{__version__}")
else:
raise ValueError(f"command not found: {sys.argv[1]}")

else:
raise ValueError(f"Expected 1 command, but got {len(sys.argv) -1}")


if __name__ == "__main__":
_log_version()
10 changes: 10 additions & 0 deletions symmetria/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from symmetria.cli.cli import run_command_line_interface


def main() -> None:
"""Entry point for the command line interface."""
run_command_line_interface()


if __name__ == "__main__":
main()
Empty file added symmetria/cli/__init__.py
Empty file.
59 changes: 59 additions & 0 deletions symmetria/cli/_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import sys

from symmetria import Permutation, __version__


class _Style:
"""Class to define the output messages style."""

YELLOW: str = "\033[33m"
RED: str = "\033[31m"
END: str = "\033[0m"
BOLD: str = "\033[1m"
UNDERLINE: str = "\033[4m"


def _execute_error_message(message: str, exit_code: int) -> None:
"""Print an error message in case of wrong given commands."""
sys.stderr.write(
f"{_Style.RED}{_Style.BOLD}Error:{_Style.END} {message}. \n "
f"For more information, try `{_Style.YELLOW}--help{_Style.END}`, or `{_Style.YELLOW}-h{_Style.END}`. \n"
)
sys.exit(exit_code)


def _execute_help_command() -> None:
"""Execute the `--help`, or `-h`, command."""
sys.stdout.write(
"Symmetria, an intuitive framework for working with the symmetric group and its elements.\n"
"\n"
f"{_Style.UNDERLINE}Usage:{_Style.END} symmetria <ARGUMENT> [OPTIONS] \n"
"\n"
f"{_Style.UNDERLINE}Options:{_Style.END} \n"
" -h, --help Print help \n"
" -v, --version Print version \n"
"\n"
f"{_Style.UNDERLINE}Argument (optional):{_Style.END} \n"
" permutation A permutation you want to learn more about. \n"
" The permutation must be given in its one-line format, i.e., \n"
" for the permutation Permutation(2, 3, 1), write 231. \n"
)
sys.exit(0)


def _execute_permutation_command(permutation: str) -> None:
"""Execute the command when a permutation is given."""
permutation = _parse_permutation(permutation=permutation)
sys.stdout.write(permutation.describe() + "\n")
sys.exit(0)


def _execute_version_command() -> None:
"""Execute the `--version`, or `-v`, command."""
sys.stdout.write(f"{_Style.BOLD}v{_Style.END}{__version__}" + "\n")
sys.exit(0)


def _parse_permutation(permutation: str) -> Permutation:
"""Convert the provided string into a `Permutation` object."""
return Permutation(*[int(d) for d in permutation])
56 changes: 56 additions & 0 deletions symmetria/cli/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import sys

from symmetria.cli._commands import (
_Style,
_execute_help_command,
_execute_error_message,
_execute_version_command,
_execute_permutation_command,
)


def run_command_line_interface() -> None:
"""Run and manage the command line interface."""
commands = sys.argv[1:]

# case where no commands are provided
if len(commands) == 0:
_execute_error_message(
message="no command provided",
exit_code=1,
)

# case where one command is provided
elif len(commands) == 1:
command = commands[0]
if _is_a_flag(command=command):
if command in {"-h", "--help"}:
_execute_help_command()
elif command in {"-v", "--version"}:
_execute_version_command()
_execute_error_message(
message=f"unexpected argument `{_Style.YELLOW}{command}{_Style.END}` found",
exit_code=1,
)
elif _is_a_permutation(command=command):
_execute_permutation_command(permutation=command)
_execute_error_message(
message=f"unexpected argument `{_Style.YELLOW}{command}{_Style.END}` found",
exit_code=1,
)

# otherwise
_execute_error_message(
message=f"Expected 1 command, but got {_Style.YELLOW}{len(sys.argv) - 1}{_Style.END} commands",
exit_code=1,
)


def _is_a_flag(command: str) -> bool:
"""Check if an argument has to be interpreted as a flag."""
return command.startswith(("-", "--"))


def _is_a_permutation(command: str) -> bool:
"""Check if an argument has to be interpreted as a permutation."""
return command.isdigit()
Empty file added tests/tests_cli/__init__.py
Empty file.
26 changes: 26 additions & 0 deletions tests/tests_cli/test_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from symmetria import Permutation

TEST_IS_A_FLAG = [
("", False),
("not-a-flag", False),
("-flag", True),
("--flag", True),
("-_still a flag", True),
("-_still-dr-dre", True),
]
TEST_IS_PERMUTATION = [
("", False),
("asd", False),
("12 34", False),
("123-hello", False),
("hello-world", False),
("123,456", False),
("13245", True),
("1", True),
("23451", True),
]
TEST_PARSE_PERMUTATION = [
("123", Permutation(1, 2, 3)),
("2341", Permutation(2, 3, 4, 1)),
("2143", Permutation(2, 1, 4, 3)),
]
Loading
Loading