From e26cf4512dbee21ba13ba8f97876b9f88b362ba0 Mon Sep 17 00:00:00 2001 From: Tim Case Date: Tue, 21 Apr 2026 20:46:13 -0500 Subject: [PATCH 1/7] Refreshing more docs --- Makefile | 6 +- docsite/source/conf.py | 8 +- docsite/source/conf.py.in | 257 -------------------------------------- 3 files changed, 7 insertions(+), 264 deletions(-) delete mode 100644 docsite/source/conf.py.in diff --git a/Makefile b/Makefile index c051abf..f94b268 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ docs-venv: fi . $(DOCSVENV)/bin/activate && pip install -q -r doc-requirements.txt -docs: docs-venv conf.py $(MANPAGES) docsite/source/index.rst +docs: docs-venv $(MANPAGES) docsite/source/index.rst . $(DOCSVENV)/bin/activate && cd docsite && make html # Add examples to the RTD docs by taking it from the README @@ -94,10 +94,6 @@ viewcover: ci-unittests xdg-open htmlcov/index.html; \ fi -conf.py: docsite/source/conf.py.in - sed "s/%VERSION%/$(VERSION)/" $< > docsite/source/conf.py - - build: clean @echo "#############################################" @echo "# Building sdist + wheel" diff --git a/docsite/source/conf.py b/docsite/source/conf.py index 29683c7..a55bb0b 100644 --- a/docsite/source/conf.py +++ b/docsite/source/conf.py @@ -12,6 +12,10 @@ # serve to show the default. import sys, os + +_version_file = os.path.join(os.path.dirname(__file__), '..', '..', 'VERSION') +with open(_version_file) as _vf: + _version = _vf.read().strip() try: import sphinx_rtd_theme except ImportError: @@ -55,9 +59,9 @@ # built documents. # # The short X.Y version. -version = '2.0.0' +version = _version # The full version, including alpha/beta/rc tags. -release = '2.0.0' +release = _version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docsite/source/conf.py.in b/docsite/source/conf.py.in deleted file mode 100644 index 0d50a27..0000000 --- a/docsite/source/conf.py.in +++ /dev/null @@ -1,257 +0,0 @@ -# -*- coding: utf-8 -*- -# -# bitmath documentation build configuration file, created by -# sphinx-quickstart on Sun Jul 13 20:40:01 2014. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os -try: - import sphinx_rtd_theme -except ImportError: - _RTD_THEME = False - pass -else: - _RTD_THEME = True - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../../bitmath')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'sphinx.ext.mathjax'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'bitmath' -copyright = u'2014-2026, Tim Case' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '%VERSION%' -# The full version, including alpha/beta/rc tags. -release = '%VERSION%' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [ - 'appendices/mixed_math.rst', - 'appendices/*', - 'example_block_devices.rst', - 'query_device_capacity_warning.rst' -] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -if _RTD_THEME: - html_theme = "sphinx_rtd_theme" -else: - html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%Y-%m-%d - %H:%M:%S %Z' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_domain_indices = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -html_show_sphinx = False - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'bitmathdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'bitmath.tex', u'bitmath Documentation', - u'Tim Case', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'bitmath', u'bitmath Documentation', - [u'Tim Case'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'bitmath', u'bitmath Documentation', - u'Tim Case', 'bitmath', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' From 45adbb0190e914a9a38bb168aea6a1616e2995ff Mon Sep 17 00:00:00 2001 From: Tim Case Date: Tue, 21 Apr 2026 20:46:55 -0500 Subject: [PATCH 2/7] Also delete the input spec file --- NEWS.rst | 4 +- python-bitmath.spec.in | 282 ----------------------------------------- 2 files changed, 2 insertions(+), 284 deletions(-) delete mode 100644 python-bitmath.spec.in diff --git a/NEWS.rst b/NEWS.rst index dbd1d38..994b2dd 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -39,7 +39,7 @@ Breaking Changes The old name still works but emits a :exc:`DeprecationWarning`. **bitmath.integrations removed** - The argparse, click, and progressbar integrations have been removed + The ``argparse``, ``click``, and ``progressbar`` integrations have been removed from the package. Copy-paste replacements are provided in the new :ref:`Integration Examples ` documentation chapter. No changes to calling code are required — just a local @@ -81,7 +81,7 @@ still works exactly the same way. What 2.0.0 adds on top of that: `_. **bitmath.sum() and built-in sum()** - A new :func:`bitmath.sum` function returns a unit-normalised result + A new :func:`bitmath.sum` function returns a unit-normalized result when summing mixed-type iterables. For uniform collections, the built-in :py:func:`sum` now works directly on bitmath sequences without a ``start=`` argument. diff --git a/python-bitmath.spec.in b/python-bitmath.spec.in deleted file mode 100644 index bed1b0b..0000000 --- a/python-bitmath.spec.in +++ /dev/null @@ -1,282 +0,0 @@ -%if 0%{?rhel} && 0%{?rhel} <= 6 -%{!?__python2: %global __python2 /usr/bin/python2} -%{!?python2_sitelib: %global python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} -%{!?python2_sitearch: %global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} -%{!?py2_build: %global py2_build python setup.py build} -%{!?py2_install: %global py2_install python setup.py install -O1 --root=$RPM_BUILD_ROOT} -%endif - -%if 0%{?fedora} -%{!?python3_version: %global python3_version %(%{__python3} -c "import sys; sys.stdout.write(sys.version[:3])")} -%global with_python3 1 -%else -%global with_python3 0 -%endif - -%global _short_name bitmath -%global _short_release 1 - -Name: python-bitmath -Summary: Aids representing and manipulating file sizes in various prefix notations -Version: %VERSION% -Release: %{_short_release}%{?dist} - -Group: Development/Libraries -License: BSD -Source0: https://github.com/tbielawa/bitmath/archive/%{version}.%{_short_release}.tar.gz -Url: https://github.com/tbielawa/bitmath - -BuildArch: noarch -BuildRequires: python2-mock -BuildRequires: python2-nose -BuildRequires: python2-progressbar -BuildRequires: python2-setuptools -BuildRequires: python2-devel -%if 0%{?with_python3} -BuildRequires: python3-devel -BuildRequires: python3-mock -BuildRequires: python3-nose -BuildRequires: python3-setuptools -%endif -%{?el6:Requires: python-argparse} -%{?el6:BuildRequires: python-argparse} -%{?el6:BuildRequires: python-unittest2} - -%description -bitmath simplifies many facets of interacting with file sizes in -various units. Examples include: converting between SI and NIST prefix -units (GiB to kB), converting between units of the same type (SI to -SI, or NIST to NIST), basic arithmetic operations (subtracting 42KiB -from 50GiB), and rich comparison operations (1024 Bytes == 1KiB), -bitwise operations, sorting, automatic best human-readable prefix -selection, and completely customizable formatting. - -In addition to the conversion and math operations, bitmath provides -human readable representations of values which are suitable for use in -interactive shells as well as larger scripts and applications. It can -also read the capacity of system storage devices. bitmath can parse -strings (like "1 KiB") into proper objects and has support for -integration with the argparse module as a custom argument type and the -progressbar module as a custom file transfer speed widget. - -bitmath is thoroughly unittested, with almost 200 individual tests (a -number which is always increasing). bitmath's test-coverage is almost -always at 100%. - -###################################################################### -# Sub-package setup -%package -n python2-bitmath -Summary: Aids representing and manipulating file sizes in various prefix notations -%{?python_provide:%python_provide python2-bitmath} - -%description -n python2-bitmath -bitmath simplifies many facets of interacting with file sizes in -various units. Examples include: converting between SI and NIST prefix -units (GiB to kB), converting between units of the same type (SI to -SI, or NIST to NIST), basic arithmetic operations (subtracting 42KiB -from 50GiB), and rich comparison operations (1024 Bytes == 1KiB), -bitwise operations, sorting, automatic best human-readable prefix -selection, and completely customizable formatting. - -In addition to the conversion and math operations, bitmath provides -human readable representations of values which are suitable for use in -interactive shells as well as larger scripts and applications. It can -also read the capacity of system storage devices. bitmath can parse -strings (like "1 KiB") into proper objects and has support for -integration with the argparse module as a custom argument type and the -progressbar module as a custom file transfer speed widget. - -bitmath is thoroughly unittested, with almost 200 individual tests (a -number which is always increasing). bitmath's test-coverage is almost -always at 100%. - -#--------------------------------------------------------------------- - -%if 0%{?with_python3} -%package -n python3-bitmath -Summary: Aids representing and manipulating file sizes in various prefix notations -%{?python_provide:%python_provide python3-bitmath} - -%description -n python3-bitmath -bitmath simplifies many facets of interacting with file sizes in -various units. Examples include: converting between SI and NIST prefix -units (GiB to kB), converting between units of the same type (SI to -SI, or NIST to NIST), basic arithmetic operations (subtracting 42KiB -from 50GiB), and rich comparison operations (1024 Bytes == 1KiB), -bitwise operations, sorting, automatic best human-readable prefix -selection, and completely customizable formatting. - -In addition to the conversion and math operations, bitmath provides -human readable representations of values which are suitable for use in -interactive shells as well as larger scripts and applications. It can -also read the capacity of system storage devices. bitmath can parse -strings (like "1 KiB") into proper objects and has support for -integration with the argparse module as a custom argument type and the -progressbar module as a custom file transfer speed widget. - -bitmath is thoroughly unittested, with almost 200 individual tests (a -number which is always increasing). bitmath's test-coverage is almost -always at 100%. -%endif # with_python3 - -###################################################################### -%check -nosetests -v - -%if 0%{?with_python3} -# We can't run the progressbar and argparse tests in python3 until -# progressbar has a python3 package available :( -# -# Skip those tests for now and run the rest -nosetests-%{python3_version} -e 'test_FileTransferSpeed' \ - -e 'test_BitmathType_' \ - -I '.*test_argparse_type.py' \ - -I '.*test_progressbar.py' -v -%endif # with_python3 - -###################################################################### -%prep -%setup -n bitmath-%{version}.%{_short_release} -q - -###################################################################### -%build -%py2_build -%if 0%{?with_python3} -%py3_build -%endif - -###################################################################### -%install -%py2_install -mv $RPM_BUILD_ROOT/%{_bindir}/bitmath $RPM_BUILD_ROOT/%{_bindir}/bitmath-2.7 - -%if 0%{?with_python3} -%py3_install -pushd $RPM_BUILD_ROOT/%{_bindir}/ -ln -s bitmath bitmath-%{python3_version} -popd -%endif # with_python3 - -mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1/ -cp -v *.1 $RPM_BUILD_ROOT/%{_mandir}/man1/ -mkdir -p $RPM_BUILD_ROOT/%{_docdir}/%{name}/docs -cp -v -r docsite/source/* $RPM_BUILD_ROOT/%{_docdir}/%{name}/docs/ -rm -f $RPM_BUILD_ROOT/%{_docdir}/%{name}/docs/NEWS.rst - -###################################################################### -%files -n python2-bitmath -%{python2_sitelib}/* -%doc README.rst NEWS.rst LICENSE -%doc %{_mandir}/man1/bitmath.1* -%doc %{_docdir}/%{name}/docs/ -%{_bindir}/bitmath-2.7 - -%if 0%{?with_python3} -%files -n python3-bitmath -%{python3_sitelib}/* -%doc README.rst NEWS.rst LICENSE -%doc %{_mandir}/man1/bitmath.1* -%doc %{_docdir}/%{name}/docs/ -%{_bindir}/bitmath -%{_bindir}/bitmath-%{python3_version} -%endif # with_python3 - -###################################################################### -%changelog -* Thu Aug 23 2018 Tim Bielawa - 1.3.3-1 - - New release - -* Sat Mar 17 2018 Tim Bielawa - 1.3.2-1 -- New release - -* Sun Jul 17 2016 Tim Bielawa - 1.3.1-1 -- New release - -* Tue Jan 12 2016 Tim Bielawa - 1.3.0-2 -- Packaging update - -* Fri Jan 8 2016 Tim Bielawa - 1.3.0-1 -- Fix best_prefix for negative values GitHub: #55 - -* Tue Dec 29 2015 Tim Bielawa - 1.2.4-3 -- Fix tests to run on koji -- Minor packaging changes - -* Mon Nov 30 2015 Tim Bielawa - 1.2.4-1 -- New release. Now builds dual python2.x and 3.x packages. -- New function: query_device_capacity -- Minor bug fixes for everyone! - -* Sun Jan 4 2015 Tim Bielawa - 1.2.3-3 -- Add mock to build requires - -* Sun Jan 4 2015 Tim Bielawa - 1.2.3-2 -- Add python-progressbar build-dependency to satisfy 'check' tests - -* Sun Jan 4 2015 Tim Bielawa - 1.2.3-1 -- Add progressbar example to the README - -* Sun Jan 4 2015 Tim Bielawa - 1.2.2-1 -- Fix some problems with the automated build system - -* Sun Jan 4 2015 Tim Bielawa - 1.2.1-1 -- Add a new integration: the progressbar module FileTransferSpeed widget - -* Mon Dec 29 2014 Tim Bielawa - 1.2.0-1 -- Add argparse integration with a BitmathType argument type - -* Sat Dec 20 2014 Tim Bielawa - 1.1.0-1 -- New parse_string utility function from tonycpsu -- 'bitmath' tool added for converting on the command line - -* Fri Aug 15 2014 Tim Bielawa - 1.0.8-3 -- Actually fix this whole specfile and version mixup - -* Fri Aug 15 2014 Tim Bielawa - 1.0.8-2 -- Fix macro expansion in specfile changelog - -* Thu Aug 14 2014 Tim Bielawa - 1.0.8-1 -- First release with contributors: davidfischer-ch and hikusukih! Thank you! -- Real documentation (via readthedocs.org) -- Significant formatting functionality added: -- +formatting context manager, listdir, getsize -- Python3 compat via rtruediv contribution! -- So many more unit tests -- Coveralls code-coverage review -- Pluralization/singularity in string formatting (thanks for the contribution!) - -* Sat Jul 19 2014 Tim Bielawa - 1.0.7-1 -- Lots of documentation and unittest updates -- See GitHub Milestone 2: 1.0.7 for a list of closed issues - -* Mon Jul 14 2014 Tim Bielawa - 1.0.6-1 -- New instance properties -- Custom representation formatting method. #9 -- Best-prefix guessing: select the best human-readable prefix unit - automatically. #6 -- Bitwise operation support. #3 -- More unittests than your body has room for - -* Mon Apr 28 2014 Tim Bielawa - 1.0.5-1 -- Now with support for bitwise operations - -* Thu Mar 20 2014 Tim Bielawa - 1.0.4-1 -- Plenty of documentation updates -- Fix some issues with mix-type math operations. -- More unit tests! - -* Mon Mar 17 2014 Tim Bielawa - 1.0.3-1 -- Big issue converting NIST to SI -- Also, retroactively remove unexpanded macros from changelog - -* Thu Mar 13 2014 Tim Bielawa - 1.0.2-3 -- Bump release for new archive format - -* Thu Mar 13 2014 Tim Bielawa - 1.0.2-2 -- Bump spec for proper Source0 versioning - -* Thu Mar 13 2014 Tim Bielawa - 1.0.2-1 -- First real solid release with full functionality and documentation - -* Tue Mar 11 2014 Tim Bielawa - 1.0.0-1 -- First release From 7ded18b26fcb60da3615c3c49980213067d23ef7 Mon Sep 17 00:00:00 2001 From: Tim Case Date: Wed, 22 Apr 2026 18:44:01 -0500 Subject: [PATCH 3/7] Remove Python 2 unittest2 compat shim from tests/__init__.py --- tests/__init__.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index eda90bc..8bd7c4c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -25,12 +25,7 @@ # SOFTWARE. -import platform -(major, minor, patch) = platform.python_version_tuple() -if int(major) == 2 and int(minor) < 7: - import unittest2 as unittest -else: - import unittest +import unittest class TestCase(unittest.TestCase): From aa0fbb0452ee36e90d3a811ccc0092eb90b3fa05 Mon Sep 17 00:00:00 2001 From: Tim Case Date: Wed, 22 Apr 2026 18:50:06 -0500 Subject: [PATCH 4/7] Add type hints to module-level functions and simple Bitmath methods Closes #120 --- bitmath/__init__.py | 57 +++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/bitmath/__init__.py b/bitmath/__init__.py index a2edaed..35e2342 100644 --- a/bitmath/__init__.py +++ b/bitmath/__init__.py @@ -42,6 +42,8 @@ # pragma: no cover """ +from __future__ import annotations + import argparse import contextlib import fnmatch @@ -53,6 +55,9 @@ import sys import threading +from collections.abc import Generator, Iterable, Iterator +from typing import IO, Any + # For device capacity reading in query_device_capacity(). Only supported # on posix systems for now. Will be addressed in issue #52 on GitHub. if os.name == 'posix': @@ -157,12 +162,12 @@ def _get_bestprefix(): return getattr(_thread_local, 'bestprefix', False) -def os_name(): +def os_name() -> str: # makes unittesting platform specific code easier return os.name -def capitalize_first(s): +def capitalize_first(s: str) -> str: """Capitalize ONLY the first letter of the input `s` * returns a copy of input `s` with the first letter capitalized @@ -178,7 +183,7 @@ class Bitmath(object): """The base class for all the other prefix classes""" # All the allowed input types - valid_types = (int, float) + valid_types: tuple[type, ...] = (int, float) def __init__(self, value=0, bytes=None, bits=None): """Instantiate with `value` by the unit, in plain bytes, or @@ -229,18 +234,18 @@ def __init__(self, value=0, bytes=None, bits=None): # We have the fundamental unit figured out. Set the 'pretty' unit self._set_prefix_value() - def _set_prefix_value(self): + def _set_prefix_value(self) -> None: self.prefix_value = self._to_prefix_value(self._byte_value) - def _to_prefix_value(self, value): + def _to_prefix_value(self, value: float) -> float: """Return the number of bits/bytes as they would look like if we converted *to* this unit""" return value / float(self._unit_value) - def _setup(self): + def _setup(self) -> tuple: raise NotImplementedError("The base 'bitmath.Bitmath' class can not be used directly") - def _do_setup(self): + def _do_setup(self) -> None: """Setup basic parameters for this class. `base` is the numeric base which when raised to `power` is equivalent @@ -253,7 +258,7 @@ def _do_setup(self): (self._base, self._power, self._name_singular, self._name_plural) = self._setup() self._unit_value = self._base ** self._power - def _norm(self, value): + def _norm(self, value: int | float) -> None: """Normalize the input value into the fundamental unit for this prefix type. @@ -401,19 +406,19 @@ def from_other(cls, item): # # Reference: https://docs.python.org/3/reference/datamodel.html#basic-customization - def __repr__(self): + def __repr__(self) -> str: """Representation of this object as you would expect to see in an interpreter""" global _FORMAT_REPR # noqa: F824 return self.format(_FORMAT_REPR) - def __str__(self): + def __str__(self) -> str: """String representation of this object""" if _get_bestprefix(): return self.best_prefix().format(_get_format_string()) return self.format(_get_format_string()) - def __format__(self, fmt_spec): + def __format__(self, fmt_spec: str) -> str: """Support Python's string formatting protocol. When *fmt_spec* is empty, returns ``str(self)`` — the same as the @@ -432,7 +437,7 @@ def __format__(self, fmt_spec): return str(self) return self.value.__format__(fmt_spec) - def format(self, fmt): + def format(self, fmt: str) -> str: """Return a representation of this instance formatted with user supplied syntax""" _fmt_params = { @@ -912,11 +917,11 @@ def __rtruediv__(self, other): - float(KiB(3.336)) would return 3.336 """ - def __int__(self): + def __int__(self) -> int: """Return this instances prefix unit as an integer""" return int(self.prefix_value) - def __float__(self): + def __float__(self) -> float: """Return this instances prefix unit as a floating point number""" return float(self.prefix_value) @@ -1262,7 +1267,7 @@ def _setup(self): ###################################################################### # Utility functions -def best_prefix(bytes, system=NIST): +def best_prefix(bytes: Bitmath | int | float, system: int = NIST) -> Bitmath: """Return a bitmath instance representing the best human-readable representation of the number of bytes given by ``bytes``. In addition to a numeric type, the ``bytes`` parameter may also be a bitmath type. @@ -1289,7 +1294,7 @@ def best_prefix(bytes, system=NIST): return Byte(value).best_prefix(system=system) -def query_device_capacity(device_fd): +def query_device_capacity(device_fd: IO[Any]) -> Byte: """Create bitmath instances of the capacity of a system block device Make one or more ioctl request to query the capacity of a block @@ -1422,7 +1427,7 @@ def query_device_capacity(device_fd): return Byte(platform_params['func'](results)) -def getsize(path, bestprefix=True, system=NIST): +def getsize(path: str, bestprefix: bool = True, system: int = NIST) -> Bitmath: """Return a bitmath instance in the best human-readable representation of the file size at `path`. Optionally, provide a preferred unit system by setting `system` to either `bitmath.NIST` (default) or @@ -1439,8 +1444,14 @@ def getsize(path, bestprefix=True, system=NIST): return Byte(size_bytes) -def listdir(search_base, followlinks=False, filter='*', - relpath=False, bestprefix=False, system=NIST): +def listdir( + search_base: str, + followlinks: bool = False, + filter: str = '*', + relpath: bool = False, + bestprefix: bool = False, + system: int = NIST, +) -> Iterator[tuple[str, Bitmath]]: """This is a generator which recurses the directory tree `search_base`, yielding 2-tuples of: @@ -1482,7 +1493,7 @@ def listdir(search_base, followlinks=False, filter='*', yield (_return_path, getsize(_path, bestprefix=bestprefix, system=system)) -def parse_string(s, system=NIST, strict=True): +def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = True) -> Bitmath: """Parse a string with units and return a bitmath instance. String inputs may include whitespace characters between the value and @@ -1626,7 +1637,7 @@ def parse_string(s, system=NIST, strict=True): return unit_class(float(val)) -def parse_string_unsafe(s, system=NIST): +def parse_string_unsafe(s: str | numbers.Number, system: int = NIST) -> Bitmath: """Deprecated wrapper for ``parse_string(s, strict=False, system=system)``. .. deprecated:: 2.0.0 @@ -1652,7 +1663,7 @@ def parse_string_unsafe(s, system=NIST): return parse_string(s, system=system, strict=False) -def sum(iterable, start=None): +def sum(iterable: Iterable[Bitmath], start: Bitmath | None = None) -> Bitmath: """Sum an iterable of bitmath instances, returning a Byte by default. The built-in sum() also works with bitmath objects: the __radd__ @@ -1673,7 +1684,7 @@ def sum(iterable, start=None): ###################################################################### # Context Managers @contextlib.contextmanager -def format(fmt_str=None, plural=False, bestprefix=False): +def format(fmt_str: str | None = None, plural: bool = False, bestprefix: bool = False) -> Generator[None, None, None]: """Thread-safe context manager for printing bitmath instances. ``fmt_str`` - a formatting mini-language compatible string. See From 4f6d27066bc54519e3b119b796f0a2b07ee5156b Mon Sep 17 00:00:00 2001 From: Tim Case Date: Wed, 22 Apr 2026 18:51:54 -0500 Subject: [PATCH 5/7] Rename assertListEqual -> assertListEqualUnordered to stop shadowing stdlib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix pyflakes F821 issues in bitmath/__init__.py - Drop explicit (object) base from class Bitmath (modern Python syntax) - Remove unnecessary global _FORMAT_REPR declaration (F823 unused global) - Fix redundant single-type isinstance tuples: isinstance(s, (str)) → isinstance(s, str) These changes modernize the code for Python 3 while maintaining all functionality. All 292 tests pass with 100% coverage. Convert % format strings to f-strings; update stale Py2 docs URL Replace list([...]).index(True) with next(enumerate()) in parse_string Fix fcntl.ioctl buffer: pass int size instead of str (Python 3 correctness) Remove os_name() wrapper — use os.name directly, patch via bitmath.os.name in tests --- bitmath/__init__.py | 69 +++++++++++------------------ tests/__init__.py | 5 +-- tests/test_file_size.py | 12 ++--- tests/test_query_device_capacity.py | 7 +-- 4 files changed, 37 insertions(+), 56 deletions(-) diff --git a/bitmath/__init__.py b/bitmath/__init__.py index 35e2342..08a0073 100644 --- a/bitmath/__init__.py +++ b/bitmath/__init__.py @@ -162,11 +162,6 @@ def _get_bestprefix(): return getattr(_thread_local, 'bestprefix', False) -def os_name() -> str: - # makes unittesting platform specific code easier - return os.name - - def capitalize_first(s: str) -> str: """Capitalize ONLY the first letter of the input `s` @@ -179,7 +174,7 @@ def capitalize_first(s: str) -> str: ###################################################################### # Base class for everything else -class Bitmath(object): +class Bitmath: """The base class for all the other prefix classes""" # All the allowed input types @@ -269,11 +264,10 @@ def _norm(self, value: int | float) -> None: self._byte_value = float(value) * self._unit_value self._bit_value = self._byte_value * 8.0 else: - raise ValueError("Initialization value '%s' is of an invalid type: %s. " - "Must be one of %s" % ( - value, - type(value), - ", ".join(str(x) for x in self.valid_types))) + raise ValueError( + f"Initialization value '{value}' is of an invalid type: {type(value)}. " + f"Must be one of {', '.join(str(x) for x in self.valid_types)}" + ) ################################################################## # Properties @@ -314,8 +308,7 @@ def system(self): # I don't expect to ever encounter this logic branch, but # hey, it's better to have extra test coverage than # insufficient test coverage. - raise ValueError("Instances mathematical base is an unsupported value: %s" % ( - str(self._base))) + raise ValueError(f"Instances mathematical base is an unsupported value: {self._base}") @property def unit(self): @@ -398,8 +391,7 @@ def from_other(cls, item): if isinstance(item, Bitmath): return cls(bits=item.bits) else: - raise ValueError("The provided items must be a valid bitmath class: %s" % - str(item.__class__)) + raise ValueError(f"The provided items must be a valid bitmath class: {item.__class__}") ###################################################################### # The following implement the Python datamodel customization methods @@ -409,7 +401,6 @@ def from_other(cls, item): def __repr__(self) -> str: """Representation of this object as you would expect to see in an interpreter""" - global _FORMAT_REPR # noqa: F824 return self.format(_FORMAT_REPR) def __str__(self) -> str: @@ -782,7 +773,7 @@ def __ge__(self, other): # Basic math operations ################################################################## - # Reference: http://docs.python.org/2.7/reference/datamodel.html#emulating-numeric-types + # Reference: https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types """These methods are called to implement the binary arithmetic operations (+, -, *, //, %, divmod(), pow(), **, <<, >>, &, ^, |). For @@ -1314,8 +1305,8 @@ def query_device_capacity(device_fd: IO[Any]) -> Byte: :return: a bitmath :class:`bitmath.Byte` instance equivalent to the capacity of the target device in bytes. """ - if os_name() != 'posix': - raise NotImplementedError("'bitmath.query_device_capacity' is not supported on this platform: %s" % os_name()) + if os.name != 'posix': + raise NotImplementedError(f"'bitmath.query_device_capacity' is not supported on this platform: {os.name}") s = os.stat(device_fd.name).st_mode if not stat.S_ISBLK(s): @@ -1408,15 +1399,12 @@ def query_device_capacity(device_fd: IO[Any]) -> Byte: for req_name, fmt, request_code in platform_params['request_params']: # Read the systems native size (in bytes) of this format type. buffer_size = struct.calcsize(fmt) - # Construct a buffer to store the ioctl result in - buffer = ' ' * buffer_size - # This code has been ran on only a few test systems. If it's # appropriate, maybe in the future we'll add try/except # conditions for some possible errors. Really only for cases # where it would add value to override the default exception # message string. - buffer = fcntl.ioctl(device_fd.fileno(), request_code, buffer) + buffer = fcntl.ioctl(device_fd.fileno(), request_code, buffer_size) # Unpack the raw result from the ioctl call into a familiar # python data type according to the ``fmt`` rules. @@ -1534,16 +1522,15 @@ def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = Tru """ if strict: # Strings only please - if not isinstance(s, (str)): - raise ValueError("parse_string only accepts string inputs but a %s was given" % - type(s)) + if not isinstance(s, str): + raise ValueError(f"parse_string only accepts string inputs but a {type(s)} was given") # get the index of the first alphabetic character try: - index = list([i.isalpha() for i in s]).index(True) - except ValueError: - # If there's no alphabetic characters we won't be able to .index(True) - raise ValueError("No unit detected, can not parse string '%s' into a bitmath object" % s) + index = next(i for i, c in enumerate(s) if c.isalpha()) + except StopIteration: + # If there's no alphabetic characters we won't be able to find a match + raise ValueError(f"No unit detected, can not parse string '{s}' into a bitmath object") # split the string into the value and the unit val, unit = s[:index], s[index:] @@ -1555,7 +1542,7 @@ def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = Tru unit_class = Byte else: if not (hasattr(sys.modules[__name__], unit) and isinstance(getattr(sys.modules[__name__], unit), type)): - raise ValueError("The unit %s is not a valid bitmath unit" % unit) + raise ValueError(f"The unit {unit} is not a valid bitmath unit") unit_class = globals()[unit] try: @@ -1565,21 +1552,19 @@ def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = Tru try: return unit_class(val) except: # pragma: no cover - raise ValueError("Can't parse string %s into a bitmath object" % s) + raise ValueError(f"Can't parse string {s} into a bitmath object") else: # strict=False path (formerly parse_string_unsafe) - if not isinstance(s, (str)) and \ - not isinstance(s, numbers.Number): - raise ValueError("parse_string only accepts string/number inputs but a %s was given" % - type(s)) + if not isinstance(s, str) and not isinstance(s, numbers.Number): + raise ValueError(f"parse_string only accepts string/number inputs but a {type(s)} was given") # Test case: raw number input (easy!) if isinstance(s, numbers.Number): return Byte(s) # Test case: a number pretending to be a string - if isinstance(s, (str)): + if isinstance(s, str): try: return Byte(float(s)) except ValueError: @@ -1588,9 +1573,9 @@ def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = Tru # At this point the input is a string with a unit component. # Separate the number and the unit. try: - index = list([i.isalpha() for i in s]).index(True) - except ValueError: # pragma: no cover - raise ValueError("No unit detected, can not parse string '%s' into a bitmath object" % s) + index = next(i for i, c in enumerate(s) if c.isalpha()) + except StopIteration: # pragma: no cover + raise ValueError(f"No unit detected, can not parse string '{s}' into a bitmath object") val, unit = s[:index], s[index:] @@ -1627,12 +1612,12 @@ def parse_string(s: str | numbers.Number, system: int = NIST, strict: bool = Tru if unit[:2] in NIST_PREFIXES: unit_class = globals()[unit] else: - raise ValueError("The unit %s is not a valid bitmath unit" % unit) + raise ValueError(f"The unit {unit} is not a valid bitmath unit") try: unit_class except UnboundLocalError: - raise ValueError("The unit %s is not a valid bitmath unit" % unit) + raise ValueError(f"The unit {unit} is not a valid bitmath unit") return unit_class(float(val)) diff --git a/tests/__init__.py b/tests/__init__.py index 8bd7c4c..22a0243 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -33,9 +33,8 @@ class TestCase(unittest.TestCase): Parent TestCase to use for all tests. """ - def assertListEqual(self, l1, l2, msg=None): - """Assert that the contents of l1 and l2 are equal (disregarding -ordering)""" + def assertListEqualUnordered(self, l1, l2, msg=None): + """Assert that l1 and l2 contain the same elements regardless of order.""" self.assertEqual(len(l1), len(l2)) # OK, the lists are of the same size. Let's test that each diff --git a/tests/test_file_size.py b/tests/test_file_size.py index ce740cd..ef0024d 100644 --- a/tests/test_file_size.py +++ b/tests/test_file_size.py @@ -121,7 +121,7 @@ def test_listdir_nosymlinks(self): 'tests/listdir_nosymlinks/depth1/depth2/1024_byte_file' ] - self.assertListEqual(discovered_paths, expected_paths) + self.assertListEqualUnordered(discovered_paths, expected_paths) expected_sizes = [ bitmath.Byte(10.0), @@ -131,7 +131,7 @@ def test_listdir_nosymlinks(self): contents[0][1], contents[1][1] ] - self.assertListEqual(discovered_sizes, expected_sizes) + self.assertListEqualUnordered(discovered_sizes, expected_sizes) # 2018-03-18 - Commenting this out for now. This is failing during # RPM building. I have no idea why or when this began @@ -186,7 +186,7 @@ def test_listdir_symlinks_follow(self): contents[0][0], contents[1][0] ] - self.assertListEqual(discovered_paths, expected_paths) + self.assertListEqualUnordered(discovered_paths, expected_paths) # Ensure the measured size is what we expect expected_sizes = [ @@ -197,7 +197,7 @@ def test_listdir_symlinks_follow(self): contents[0][1], contents[1][1] ] - self.assertListEqual(discovered_sizes, expected_sizes) + self.assertListEqualUnordered(discovered_sizes, expected_sizes) def test_listdir_symlinks_follow_relpath_false(self): """listdir: symlinks followed, absolute paths are returned @@ -219,7 +219,7 @@ def test_listdir_symlinks_follow_relpath_false(self): contents[0][0], contents[1][0] ] - self.assertListEqual(discovered_paths, expected_paths) + self.assertListEqualUnordered(discovered_paths, expected_paths) # Ensure the measured size is what we expect expected_sizes = [ @@ -230,7 +230,7 @@ def test_listdir_symlinks_follow_relpath_false(self): contents[0][1], contents[1][1] ] - self.assertListEqual(discovered_sizes, expected_sizes) + self.assertListEqualUnordered(discovered_sizes, expected_sizes) def test_listdir_filtering_nosymlinks(self): """listdir: no symbolic links in tree measures right with a filter diff --git a/tests/test_query_device_capacity.py b/tests/test_query_device_capacity.py index 171b56c..374a772 100644 --- a/tests/test_query_device_capacity.py +++ b/tests/test_query_device_capacity.py @@ -66,12 +66,10 @@ def test_query_device_capacity_linux_everything_is_wonderful(self): ioctl.return_value = struct.pack('L', 244140625) # = 'QJ\x8d\x0e\x00\x00\x00\x00' # = 244140625 ~= 244.140625 MB (in SI) - buffer_test = ' ' * struct.calcsize('L') - bytes = bitmath.query_device_capacity(device) self.assertEqual(bytes, 244140625) self.assertEqual(ioctl.call_count, 1) - ioctl.assert_called_once_with(4, 0x80081272, buffer_test) + ioctl.assert_called_once_with(4, 0x80081272, struct.calcsize('L')) def test_query_device_capacity_mac_everything_is_wonderful(self): """query device capacity works on a happy Mac OS X host""" @@ -120,7 +118,6 @@ def test_query_device_capacity_device_not_block(self): def test_query_device_capacity_non_posix_system_fails(self): """query device capacity fails on a non-posix host""" - with mock.patch('bitmath.os_name') as os_name: - os_name.return_value = 'nt' + with mock.patch('bitmath.os.name', 'nt'): with self.assertRaises(NotImplementedError): bitmath.query_device_capacity(device) From f32b1546f0f2a29285cb9d13cacc1170d3c6be63 Mon Sep 17 00:00:00 2001 From: Tim Case Date: Wed, 22 Apr 2026 19:10:29 -0500 Subject: [PATCH 6/7] Update CLAUDE.md: phases complete, Python 3.9+ minimum, pytest replaces nosetests --- CLAUDE.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ NEWS.rst | 22 +++++++++-------- 2 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2294392 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,74 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + + +## Project Overview + +**bitmath** is a pure-Python library (no external runtime dependencies) for representing and converting file sizes across SI (decimal) and NIST (binary) unit systems. It supports arithmetic, rich comparisons, bitwise ops, parsing, formatting, and f-string/format() support. + +## Project Direction +bitmath has been around for almost 12 years, and over that lifetime it promised to deliver backwards compatibility. It delivered on that promise and gathered a strong supporting of people and eventual "critical infrastructure" project status on the PyPI.org website. + +As of January 2023 the project maintainer (me) has stated in this issue https://github.com/timlnx/bitmath/issues/99 that the project is still alive and the next release will be python 3 support only. + +Much of that porting work has already happened in the `2023-01-26-no-more-py2` branch https://github.com/timlnx/bitmath/tree/2023-01-26-no-more-py2 + +### Current State (as of 2.0.0) + +Phases 1 (maintenance 1.4.0) and 2 (bitmath 2.0.0) are complete. The project: + +- Supports **Python 3.9 and newer only** (`requires-python = ">=3.9"` in `pyproject.toml`) +- Uses `hatchling` as the build backend (replaces `setup.py`) +- Uses `pytest` as the test runner (292 tests, 99% coverage — one branch in `system` property intentionally uncovered) +- Is published on PyPI as version 2.0.0 +- Drop-in compatible with the 1.x public API + +## Common Commands + +```bash +# Run the full test suite with coverage +make test + +# Run linting +ruff check bitmath/ tests/ + +# Build a wheel +make build + +# Install in development mode +pip install -e . +``` + +Run a single test file: +```bash +python -m pytest tests/test_arithmetic.py -v +``` + +## Architecture + +Almost all logic lives in a single file: `bitmath/__init__.py` (~1650 lines). + +**Class hierarchy:** +- `Bitmath` — base class with all arithmetic, comparison, bitwise, formatting, and conversion logic + - `Byte` — byte-based units; subclasses: `KiB MiB GiB TiB PiB EiB` (NIST/base-2) and `kB MB GB TB PB EB ZB YB` (SI/base-10) + - `Bit` — bit-based units; subclasses: `Kib Mib Gib Tib Pib Eib` (NIST) and `kb Mb Gb Tb Pb Eb Zb Yb` (SI) + +All unit values are normalized to bits internally; conversion between units happens at construction time via `_norm_value` and class-level `_base_value` / `_unit_value` constants. + +**Key module-level functions:** +- `best_prefix(value, system=NIST)` — pick the most human-readable unit for a raw byte value +- `getsize(path, ...)` — file size with automatic prefix selection +- `listdir(search_base, ...)` — recursive directory listing with sizes +- `parse_string(s)` / `parse_string_unsafe(s, system=SI)` — string → bitmath object +- `query_device_capacity(device_fd)` — POSIX device capacity (Linux/macOS) + +**Constants:** `NIST`, `SI`, `NIST_PREFIXES`, `SI_PREFIXES`, `ALL_UNIT_TYPES` + +## Testing Notes + +- Test runner: `pytest` +- All tests are in `tests/` as `test_*.py` files +- Test case names must be unique across the suite — enforced by `tests/test_unique_testcase_names.sh` +- Coverage: 99% (one branch in `system` property intentionally uncovered) +- `unittest.mock` (stdlib) is used for patching in integration tests diff --git a/NEWS.rst b/NEWS.rst index 994b2dd..5881241 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,7 +17,7 @@ a major release. Version 2.0.0 is a thorough modernization: the Python 2 era is officially over, the library picks up several long-requested features, and the entire project infrastructure has been rebuilt from scratch. If you've been running bitmath on Python -3.11 or later and quietly wishing it felt more modern — this release +3.9 or later and quietly wishing it felt more modern — this release is for you. @@ -25,14 +25,15 @@ Breaking Changes ================ **Python support** - Python 3.11+ only. Python 2 and Python 3.7–3.10 are no longer + Python 3.9+ only. Python 2 and Python < 3.9 are no longer supported or tested. **parse_string() default system** - The default unit system when ``strict=False`` is now **NIST** - (binary). Previously it defaulted to SI. Code that relied on the - old default for ambiguous strings such as ``"1g"`` will get a - different result. See :ref:`parse-string-non-strict` for full details. + The default unit system when ``strict=False`` is now **NIST** (base-2). + Previously it defaulted to SI (base-10). Code that relied on the old default + for ambiguous strings such as ``"1g"`` could get a different result. See + :ref:`parse-string-non-strict` for full details. All bitmath now consistently + defaults to the NIST system. **parse_string_unsafe() deprecated** Use :func:`bitmath.parse_string` with ``strict=False`` instead. @@ -45,10 +46,6 @@ Breaking Changes chapter. No changes to calling code are required — just a local copy of the relevant snippet. -**Build and install** - ``setup.py`` and ``setup.py.in`` are gone. Installation is - ``pip install bitmath``. Source builds use ``python -m build``. - **Byte and Bit display names** ``Byte`` and ``Bit`` now display as ``B`` and ``b`` respectively, matching the abbreviated style of every other unit. Code that @@ -57,6 +54,11 @@ Breaking Changes ``"Byte"`` or ``"Bit"`` will need to be updated. The class names themselves are unchanged. +**Build and install** + ``setup.py`` and ``setup.py.in`` are gone. Installation is + ``pip install bitmath``. Source builds use ``python -m build``. + + Library Improvements ==================== From 15409e0c69385bf04b2f94e6bc9562dc574f928d Mon Sep 17 00:00:00 2001 From: Tim Case Date: Wed, 22 Apr 2026 19:34:30 -0500 Subject: [PATCH 7/7] Last bit wrapping up the python 3.9+ fixup --- CLAUDE.md | 6 +++--- README.rst | 8 ++++---- docsite/source/index.rst | 2 +- docsite/source/index.rst.in | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2294392..9b39122 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,10 +27,10 @@ Phases 1 (maintenance 1.4.0) and 2 (bitmath 2.0.0) are complete. The project: ## Common Commands ```bash -# Run the full test suite with coverage -make test +# Run the full test suite with coverage (creates venv, runs pytest + linting) +make ci -# Run linting +# Run linting only ruff check bitmath/ tests/ # Build a wheel diff --git a/README.rst b/README.rst index 14f74bb..dda92b3 100644 --- a/README.rst +++ b/README.rst @@ -99,14 +99,14 @@ supported `_ Python releases. $ sudo dnf install python3-bitmath -**PyPi**: +**PyPI**: -You could also install bitmath from `PyPi -`_ if you like: +You could also install bitmath from `PyPI +`_ if you like: .. code-block:: bash - $ sudo pip install bitmath + $ pip install --user bitmath diff --git a/docsite/source/index.rst b/docsite/source/index.rst index 957e8d4..137cf22 100644 --- a/docsite/source/index.rst +++ b/docsite/source/index.rst @@ -78,7 +78,7 @@ Installation bitmath is available in Fedora and EPEL repositories, as well as directly available via `PyPI -`_. As of 2023 bitmath is only +`_. As of 2023 bitmath is only developed, tested, and supported for `currently supported `_ Python releases. diff --git a/docsite/source/index.rst.in b/docsite/source/index.rst.in index 7f1b7d1..a465614 100644 --- a/docsite/source/index.rst.in +++ b/docsite/source/index.rst.in @@ -78,7 +78,7 @@ Installation bitmath is available in Fedora and EPEL repositories, as well as directly available via `PyPI -`_. As of 2023 bitmath is only +`_. As of 2023 bitmath is only developed, tested, and supported for `currently supported `_ Python releases.