baseconvert 2.0.3__tar.gz → 2.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- baseconvert-2.1.1/PKG-INFO +110 -0
- baseconvert-2.1.1/README.md +75 -0
- baseconvert-2.1.1/README.rst +90 -0
- baseconvert-2.1.1/VERSION.txt +1 -0
- baseconvert-2.1.1/baseconvert/ButtonRow.qml +80 -0
- baseconvert-2.1.1/baseconvert/__init__.py +13 -0
- baseconvert-2.1.1/baseconvert/__main__.py +90 -0
- baseconvert-2.1.1/baseconvert/app.qml +470 -0
- baseconvert-2.1.1/baseconvert/baseconvert.py +442 -0
- baseconvert-2.1.1/baseconvert/gui.py +86 -0
- baseconvert-2.1.1/baseconvert.egg-info/PKG-INFO +110 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/baseconvert.egg-info/SOURCES.txt +6 -2
- baseconvert-2.1.1/pyproject.toml +40 -0
- baseconvert-2.1.1/tests/test_baseconvert.py +188 -0
- baseconvert-2.1.1/tests/test_cli.py +60 -0
- baseconvert-2.1.1/tests/test_coverage_paths.py +173 -0
- baseconvert-2.1.1/tests/test_entry_points.py +13 -0
- baseconvert-2.0.3/PKG-INFO +0 -179
- baseconvert-2.0.3/README.md +0 -154
- baseconvert-2.0.3/README.rst +0 -160
- baseconvert-2.0.3/VERSION.txt +0 -1
- baseconvert-2.0.3/baseconvert/ButtonRow.qml +0 -108
- baseconvert-2.0.3/baseconvert/__init__.py +0 -5
- baseconvert-2.0.3/baseconvert/__main__.py +0 -51
- baseconvert-2.0.3/baseconvert/app.qml +0 -270
- baseconvert-2.0.3/baseconvert/baseconvert.py +0 -806
- baseconvert-2.0.3/baseconvert/gui.py +0 -54
- baseconvert-2.0.3/baseconvert.egg-info/PKG-INFO +0 -179
- baseconvert-2.0.3/setup.py +0 -47
- {baseconvert-2.0.3 → baseconvert-2.1.1}/LICENSE.txt +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/MANIFEST.in +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/baseconvert.egg-info/dependency_links.txt +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/baseconvert.egg-info/entry_points.txt +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/baseconvert.egg-info/requires.txt +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/baseconvert.egg-info/top_level.txt +0 -0
- {baseconvert-2.0.3 → baseconvert-2.1.1}/setup.cfg +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: baseconvert
|
|
3
|
+
Version: 2.1.1
|
|
4
|
+
Summary: Convert numbers between bases.
|
|
5
|
+
Author: squdle, BreadMakesYouFull
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: base,bases,radix,numeral system,number,hex,dec,bin,hexidecimal,binary,decimal,fraction,fractions,integer,convert,gui
|
|
8
|
+
Classifier: Programming Language :: Python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Topic :: Education
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
13
|
+
Classifier: Intended Audience :: Education
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/x-rst
|
|
16
|
+
License-File: LICENSE.txt
|
|
17
|
+
Provides-Extra: gui
|
|
18
|
+
Requires-Dist: pyside6; extra == "gui"
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
baseconvert
|
|
22
|
+
===========
|
|
23
|
+
|
|
24
|
+
Convert rational numbers between positive integer bases, with exact
|
|
25
|
+
arithmetic and recurring fractional digits.
|
|
26
|
+
|
|
27
|
+
Requires Python 3.10 or newer.
|
|
28
|
+
|
|
29
|
+
Install
|
|
30
|
+
-------
|
|
31
|
+
|
|
32
|
+
Install the library from PyPI::
|
|
33
|
+
|
|
34
|
+
python -m pip install baseconvert
|
|
35
|
+
|
|
36
|
+
For the GUI, install the optional dependencies and launch the application::
|
|
37
|
+
|
|
38
|
+
python -m pip install 'baseconvert[gui]'
|
|
39
|
+
baseconvert
|
|
40
|
+
|
|
41
|
+
Run from a source checkout
|
|
42
|
+
--------------------------
|
|
43
|
+
|
|
44
|
+
Install `just <https://just.systems/>`_, clone the repository, and run
|
|
45
|
+
``just launch``. The recipe creates ``.venv`` and installs the GUI extra if
|
|
46
|
+
the launcher or PySide6 QML module is missing, then starts the GUI::
|
|
47
|
+
|
|
48
|
+
git clone https://github.com/BreadMakesYouFull/baseconvert.git
|
|
49
|
+
cd baseconvert
|
|
50
|
+
just launch
|
|
51
|
+
|
|
52
|
+
Development recipes
|
|
53
|
+
-------------------
|
|
54
|
+
|
|
55
|
+
Run these recipes from the repository root::
|
|
56
|
+
|
|
57
|
+
just install # editable install in .venv
|
|
58
|
+
just install-gui # editable install with GUI dependencies
|
|
59
|
+
just install-dev # install build, Black, and Twine
|
|
60
|
+
just format # format Python source
|
|
61
|
+
just lint # check formatting
|
|
62
|
+
just test # run doctests
|
|
63
|
+
just check # lint, doctests, then check files already in dist/
|
|
64
|
+
just build # clean, install development tools, build sdist and wheel
|
|
65
|
+
just clean # remove build artifacts AND .venv
|
|
66
|
+
|
|
67
|
+
``just build`` first runs ``just clean``, which also deletes ``.venv``, and
|
|
68
|
+
then installs the build tools again. ``just check`` does not build
|
|
69
|
+
distributions; it runs ``twine check dist/*`` against files already in
|
|
70
|
+
``dist/``. ``just publish-test`` and ``just publish`` run ``just check`` and
|
|
71
|
+
upload the existing ``dist/*`` files to TestPyPI or PyPI, respectively. To
|
|
72
|
+
build and validate distributions before publishing, run ``just build``
|
|
73
|
+
followed by ``just check`` and review the files in ``dist/``.
|
|
74
|
+
|
|
75
|
+
Python library
|
|
76
|
+
--------------
|
|
77
|
+
|
|
78
|
+
The API accepts strings, digit tuples, integers, floats, and
|
|
79
|
+
``fractions.Fraction`` values. Use strings or ``Fraction`` to express exact
|
|
80
|
+
decimal values without float representation concerns::
|
|
81
|
+
|
|
82
|
+
from baseconvert import base
|
|
83
|
+
|
|
84
|
+
base("FF0.8", 16, 10, string=True) # '4080.5'
|
|
85
|
+
base("4080.5", 10, 16, string=True) # 'FF0.8'
|
|
86
|
+
base("-0.1", 3, 10, string=True, exact=True) # '-0.[3]'
|
|
87
|
+
|
|
88
|
+
The command-line interface reads a number argument or standard input. Bases
|
|
89
|
+
are integers; ``-s`` prints a string, and ``--no-recurring`` disables
|
|
90
|
+
recurring notation::
|
|
91
|
+
|
|
92
|
+
python -m baseconvert -n 4080.5 -i 10 -o 16 -s
|
|
93
|
+
echo 0.1 | python -m baseconvert -i 3 -o 10 --no-recurring -s
|
|
94
|
+
|
|
95
|
+
Digits, recurring fractions, and precision
|
|
96
|
+
------------------------------------------
|
|
97
|
+
|
|
98
|
+
String digits are
|
|
99
|
+
``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz``. Values
|
|
100
|
+
above 61 use ascending Unicode characters; tuple representation is
|
|
101
|
+
recommended for bases above 61. In a digit tuple, each digit is a base-10
|
|
102
|
+
integer and the radix point is ``'.'``. A leading ``'-'`` represents a
|
|
103
|
+
negative value.
|
|
104
|
+
|
|
105
|
+
Recurring digits are enclosed in square brackets, for example ``0.[3]``.
|
|
106
|
+
``max_depth`` limits fractional digits (default 10). Set ``exact=True`` or
|
|
107
|
+
``max_depth=0`` to calculate the complete terminating or repeating expansion
|
|
108
|
+
when recurring output is enabled. Exact recurring detection uses rational
|
|
109
|
+
remainders. With recurring output disabled, an unlimited expansion is bounded
|
|
110
|
+
by ``MAX_DEPTH``.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# baseconvert
|
|
2
|
+
|
|
3
|
+
Convert rational numbers between positive integer bases, with exact arithmetic and recurring fractional digits.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
[PyPI](https://pypi.org/project/baseconvert/) · [Flathub](https://flathub.org/apps/io.github.breadmakesyoufull.baseconvert) · [Windows release](https://github.com/BreadMakesYouFull/baseconvert/releases/tag/windows)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Requires Python 3.10 or newer. Install the library from PyPI:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
python -m pip install baseconvert
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For the GUI, install the optional dependencies:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
python -m pip install 'baseconvert[gui]'
|
|
21
|
+
baseconvert
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Run from a source checkout
|
|
25
|
+
|
|
26
|
+
Install [`just`](https://just.systems/), clone the repository, and run `just launch`. The recipe creates `.venv` and installs the GUI extra if the launcher or PySide6 QML module is missing, then starts the GUI:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
git clone https://github.com/BreadMakesYouFull/baseconvert.git
|
|
30
|
+
cd baseconvert
|
|
31
|
+
just launch
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Development recipes
|
|
35
|
+
|
|
36
|
+
Run these from the repository root:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
just install # editable install in .venv
|
|
40
|
+
just install-gui # editable install with GUI dependencies
|
|
41
|
+
just install-dev # install build, Black, and Twine
|
|
42
|
+
just format # format Python source
|
|
43
|
+
just lint # check formatting
|
|
44
|
+
just test # run doctests
|
|
45
|
+
just check # lint, doctests, then check files already in dist/
|
|
46
|
+
just build # clean, install development tools, build sdist and wheel
|
|
47
|
+
just clean # remove build artifacts AND .venv
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`just build` first runs `just clean`, which also deletes `.venv`, and then installs the build tools again. `just check` does not build distributions; it runs `twine check dist/*` against whatever is currently in `dist/`. `just publish-test` and `just publish` run `just check` and upload the existing `dist/*` files to TestPyPI or PyPI, respectively. To build and validate distributions before publishing, run `just build` followed by `just check` and review the files in `dist/`.
|
|
51
|
+
|
|
52
|
+
## Python library
|
|
53
|
+
|
|
54
|
+
The API accepts strings, digit tuples, integers, floats, and `fractions.Fraction` values. Use strings or `Fraction` to express exact decimal values without float representation concerns.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from baseconvert import base
|
|
58
|
+
|
|
59
|
+
base("FF0.8", 16, 10, string=True) # '4080.5'
|
|
60
|
+
base("4080.5", 10, 16, string=True) # 'FF0.8'
|
|
61
|
+
base("-0.1", 3, 10, string=True, exact=True) # '-0.[3]'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The command-line interface reads a number argument or standard input. Bases are integers; `-s` prints a string, and `--no-recurring` disables recurring notation:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
python -m baseconvert -n 4080.5 -i 10 -o 16 -s
|
|
68
|
+
echo 0.1 | python -m baseconvert -i 3 -o 10 --no-recurring -s
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Digits, recurring fractions, and precision
|
|
72
|
+
|
|
73
|
+
String digits are `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`. Values above 61 use ascending Unicode characters; tuple representation is recommended for bases above 61. In a digit tuple, each digit is a base-10 integer and the radix point is `'.'`. A leading `'-'` represents a negative value.
|
|
74
|
+
|
|
75
|
+
Recurring digits are enclosed in square brackets, for example `0.[3]`. `max_depth` limits fractional digits (default 10). Set `exact=True` or `max_depth=0` to calculate the complete terminating or repeating expansion when recurring output is enabled. Exact recurring detection uses rational remainders. With recurring output disabled, an unlimited expansion is bounded by `MAX_DEPTH`.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
baseconvert
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
Convert rational numbers between positive integer bases, with exact
|
|
5
|
+
arithmetic and recurring fractional digits.
|
|
6
|
+
|
|
7
|
+
Requires Python 3.10 or newer.
|
|
8
|
+
|
|
9
|
+
Install
|
|
10
|
+
-------
|
|
11
|
+
|
|
12
|
+
Install the library from PyPI::
|
|
13
|
+
|
|
14
|
+
python -m pip install baseconvert
|
|
15
|
+
|
|
16
|
+
For the GUI, install the optional dependencies and launch the application::
|
|
17
|
+
|
|
18
|
+
python -m pip install 'baseconvert[gui]'
|
|
19
|
+
baseconvert
|
|
20
|
+
|
|
21
|
+
Run from a source checkout
|
|
22
|
+
--------------------------
|
|
23
|
+
|
|
24
|
+
Install `just <https://just.systems/>`_, clone the repository, and run
|
|
25
|
+
``just launch``. The recipe creates ``.venv`` and installs the GUI extra if
|
|
26
|
+
the launcher or PySide6 QML module is missing, then starts the GUI::
|
|
27
|
+
|
|
28
|
+
git clone https://github.com/BreadMakesYouFull/baseconvert.git
|
|
29
|
+
cd baseconvert
|
|
30
|
+
just launch
|
|
31
|
+
|
|
32
|
+
Development recipes
|
|
33
|
+
-------------------
|
|
34
|
+
|
|
35
|
+
Run these recipes from the repository root::
|
|
36
|
+
|
|
37
|
+
just install # editable install in .venv
|
|
38
|
+
just install-gui # editable install with GUI dependencies
|
|
39
|
+
just install-dev # install build, Black, and Twine
|
|
40
|
+
just format # format Python source
|
|
41
|
+
just lint # check formatting
|
|
42
|
+
just test # run doctests
|
|
43
|
+
just check # lint, doctests, then check files already in dist/
|
|
44
|
+
just build # clean, install development tools, build sdist and wheel
|
|
45
|
+
just clean # remove build artifacts AND .venv
|
|
46
|
+
|
|
47
|
+
``just build`` first runs ``just clean``, which also deletes ``.venv``, and
|
|
48
|
+
then installs the build tools again. ``just check`` does not build
|
|
49
|
+
distributions; it runs ``twine check dist/*`` against files already in
|
|
50
|
+
``dist/``. ``just publish-test`` and ``just publish`` run ``just check`` and
|
|
51
|
+
upload the existing ``dist/*`` files to TestPyPI or PyPI, respectively. To
|
|
52
|
+
build and validate distributions before publishing, run ``just build``
|
|
53
|
+
followed by ``just check`` and review the files in ``dist/``.
|
|
54
|
+
|
|
55
|
+
Python library
|
|
56
|
+
--------------
|
|
57
|
+
|
|
58
|
+
The API accepts strings, digit tuples, integers, floats, and
|
|
59
|
+
``fractions.Fraction`` values. Use strings or ``Fraction`` to express exact
|
|
60
|
+
decimal values without float representation concerns::
|
|
61
|
+
|
|
62
|
+
from baseconvert import base
|
|
63
|
+
|
|
64
|
+
base("FF0.8", 16, 10, string=True) # '4080.5'
|
|
65
|
+
base("4080.5", 10, 16, string=True) # 'FF0.8'
|
|
66
|
+
base("-0.1", 3, 10, string=True, exact=True) # '-0.[3]'
|
|
67
|
+
|
|
68
|
+
The command-line interface reads a number argument or standard input. Bases
|
|
69
|
+
are integers; ``-s`` prints a string, and ``--no-recurring`` disables
|
|
70
|
+
recurring notation::
|
|
71
|
+
|
|
72
|
+
python -m baseconvert -n 4080.5 -i 10 -o 16 -s
|
|
73
|
+
echo 0.1 | python -m baseconvert -i 3 -o 10 --no-recurring -s
|
|
74
|
+
|
|
75
|
+
Digits, recurring fractions, and precision
|
|
76
|
+
------------------------------------------
|
|
77
|
+
|
|
78
|
+
String digits are
|
|
79
|
+
``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz``. Values
|
|
80
|
+
above 61 use ascending Unicode characters; tuple representation is
|
|
81
|
+
recommended for bases above 61. In a digit tuple, each digit is a base-10
|
|
82
|
+
integer and the radix point is ``'.'``. A leading ``'-'`` represents a
|
|
83
|
+
negative value.
|
|
84
|
+
|
|
85
|
+
Recurring digits are enclosed in square brackets, for example ``0.[3]``.
|
|
86
|
+
``max_depth`` limits fractional digits (default 10). Set ``exact=True`` or
|
|
87
|
+
``max_depth=0`` to calculate the complete terminating or repeating expansion
|
|
88
|
+
when recurring output is enabled. Exact recurring detection uses rational
|
|
89
|
+
remainders. With recurring output disabled, an unlimited expansion is bounded
|
|
90
|
+
by ``MAX_DEPTH``.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.1
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import QtQuick.Controls
|
|
3
|
+
import QtQuick.Layouts
|
|
4
|
+
|
|
5
|
+
Item {
|
|
6
|
+
id: buttonRow
|
|
7
|
+
property string text1: "1"
|
|
8
|
+
property string text2: "2"
|
|
9
|
+
property string text3: "3"
|
|
10
|
+
property string text4: "4"
|
|
11
|
+
property string text5: "5"
|
|
12
|
+
property string text6: "6"
|
|
13
|
+
property bool enable1: true
|
|
14
|
+
property bool enable2: true
|
|
15
|
+
property bool enable3: true
|
|
16
|
+
property bool enable4: true
|
|
17
|
+
property bool enable5: true
|
|
18
|
+
property bool enable6: true
|
|
19
|
+
signal buttonPressed(text: string)
|
|
20
|
+
property bool darkMode: false
|
|
21
|
+
property color color1: darkMode ? "#d8dfd2" : "#f0f0df"
|
|
22
|
+
property color colorText1: "#18211e"
|
|
23
|
+
property color color2: color1
|
|
24
|
+
property color colorText2: colorText1
|
|
25
|
+
property color color3: color1
|
|
26
|
+
property color colorText3: colorText1
|
|
27
|
+
property color color4: color1
|
|
28
|
+
property color colorText4: colorText1
|
|
29
|
+
property color color5: color1
|
|
30
|
+
property color colorText5: colorText1
|
|
31
|
+
property color color6: color1
|
|
32
|
+
property color colorText6: colorText1
|
|
33
|
+
|
|
34
|
+
RowLayout {
|
|
35
|
+
anchors.fill: parent
|
|
36
|
+
spacing: 4
|
|
37
|
+
|
|
38
|
+
Repeater {
|
|
39
|
+
model: 6
|
|
40
|
+
delegate: Button {
|
|
41
|
+
required property int index
|
|
42
|
+
property bool enabledKey: index === 0 ? buttonRow.enable1
|
|
43
|
+
: index === 1 ? buttonRow.enable2
|
|
44
|
+
: index === 2 ? buttonRow.enable3
|
|
45
|
+
: index === 3 ? buttonRow.enable4
|
|
46
|
+
: index === 4 ? buttonRow.enable5 : buttonRow.enable6
|
|
47
|
+
property string keyText: index === 0 ? buttonRow.text1
|
|
48
|
+
: index === 1 ? buttonRow.text2
|
|
49
|
+
: index === 2 ? buttonRow.text3
|
|
50
|
+
: index === 3 ? buttonRow.text4
|
|
51
|
+
: index === 4 ? buttonRow.text5 : buttonRow.text6
|
|
52
|
+
property color keyColor: index === 0 ? buttonRow.color1
|
|
53
|
+
: index === 1 ? buttonRow.color2
|
|
54
|
+
: index === 2 ? buttonRow.color3
|
|
55
|
+
: index === 3 ? buttonRow.color4
|
|
56
|
+
: index === 4 ? buttonRow.color5 : buttonRow.color6
|
|
57
|
+
property color keyTextColor: index === 0 ? buttonRow.colorText1
|
|
58
|
+
: index === 1 ? buttonRow.colorText2
|
|
59
|
+
: index === 2 ? buttonRow.colorText3
|
|
60
|
+
: index === 3 ? buttonRow.colorText4
|
|
61
|
+
: index === 4 ? buttonRow.colorText5 : buttonRow.colorText6
|
|
62
|
+
visible: enabledKey
|
|
63
|
+
Layout.fillWidth: true
|
|
64
|
+
Layout.fillHeight: true
|
|
65
|
+
text: keyText
|
|
66
|
+
font.family: "Monospace"
|
|
67
|
+
font.weight: Font.Bold
|
|
68
|
+
onClicked: buttonRow.buttonPressed(text)
|
|
69
|
+
palette.button: keyColor
|
|
70
|
+
palette.buttonText: keyTextColor
|
|
71
|
+
background: Rectangle {
|
|
72
|
+
radius: Math.min(8, height * 0.22)
|
|
73
|
+
color: parent.down ? Qt.darker(parent.keyColor, 1.12) : parent.keyColor
|
|
74
|
+
border.width: 1
|
|
75
|
+
border.color: buttonRow.darkMode ? "#f5f4e5" : "#ffffff"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from baseconvert.baseconvert import BaseConverter
|
|
2
|
+
from baseconvert.baseconvert import DigitTuple
|
|
3
|
+
from baseconvert.baseconvert import base
|
|
4
|
+
|
|
5
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
6
|
+
|
|
7
|
+
__all__ = ["BaseConverter", "DigitTuple", "base", "__version__"]
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
__version__ = version("baseconvert")
|
|
11
|
+
except PackageNotFoundError:
|
|
12
|
+
# Allow imports directly from a source checkout before installation.
|
|
13
|
+
__version__ = "0+unknown"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Convert a number from the command line, or launch the GUI with no input.
|
|
2
|
+
|
|
3
|
+
Examples::
|
|
4
|
+
|
|
5
|
+
python -m baseconvert -n 0.5 -i 10 -o 20 -s
|
|
6
|
+
echo 3.1415926 | python -m baseconvert -i 10 -o 16 -d 3 -s
|
|
7
|
+
python -m baseconvert -n 0.1 -i 3 -o 10 --no-recurring -s
|
|
8
|
+
baseconvert --theme light
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import sys
|
|
13
|
+
from typing import Sequence
|
|
14
|
+
|
|
15
|
+
from baseconvert import DigitTuple, base
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main(argv: Sequence[str] | None = None) -> str | DigitTuple | None:
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
description="Convert rational numbers between bases."
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"-n",
|
|
24
|
+
"--number",
|
|
25
|
+
default=None,
|
|
26
|
+
help="The number to convert as a string; otherwise read stdin.",
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"-i", "--input-base", type=int, default=10, help="Input base (default: 10)."
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"-o", "--output-base", type=int, default=10, help="Output base (default: 10)."
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"-d",
|
|
36
|
+
"--max-depth",
|
|
37
|
+
type=int,
|
|
38
|
+
default=10,
|
|
39
|
+
help="Maximum fractional digits (default: 10).",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--theme",
|
|
43
|
+
choices=("system", "light", "dark"),
|
|
44
|
+
default="dark",
|
|
45
|
+
help="GUI color theme (default: dark).",
|
|
46
|
+
)
|
|
47
|
+
recurring = parser.add_mutually_exclusive_group()
|
|
48
|
+
recurring.add_argument(
|
|
49
|
+
"-r",
|
|
50
|
+
"--recurring",
|
|
51
|
+
dest="recurring",
|
|
52
|
+
action="store_true",
|
|
53
|
+
help="Mark repeating fractional digits (the default).",
|
|
54
|
+
)
|
|
55
|
+
recurring.add_argument(
|
|
56
|
+
"--no-recurring",
|
|
57
|
+
dest="recurring",
|
|
58
|
+
action="store_false",
|
|
59
|
+
help="Do not mark repeating fractional digits.",
|
|
60
|
+
)
|
|
61
|
+
parser.set_defaults(recurring=True)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"-s",
|
|
64
|
+
"--string",
|
|
65
|
+
action="store_true",
|
|
66
|
+
help="Output the number as a string rather than a tuple.",
|
|
67
|
+
)
|
|
68
|
+
args = parser.parse_args(argv)
|
|
69
|
+
|
|
70
|
+
options = {
|
|
71
|
+
"string": args.string,
|
|
72
|
+
"max_depth": args.max_depth,
|
|
73
|
+
"recurring": args.recurring,
|
|
74
|
+
}
|
|
75
|
+
if args.number is not None:
|
|
76
|
+
return base(args.number, args.input_base, args.output_base, **options)
|
|
77
|
+
if not sys.stdin.isatty():
|
|
78
|
+
number = sys.stdin.read().strip()
|
|
79
|
+
return base(number, args.input_base, args.output_base, **options)
|
|
80
|
+
|
|
81
|
+
from .gui import main as gui_main
|
|
82
|
+
|
|
83
|
+
gui_main(theme=args.theme)
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
result = main()
|
|
89
|
+
if result is not None:
|
|
90
|
+
print(result)
|