Skip to content
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
38 changes: 38 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# pycommons-lang

[![PyPI](https://img.shields.io/pypi/v/pycommons-lang)](https://pypi.org/project/pycommons-lang/)
![versions](https://img.shields.io/pypi/pyversions/pycommons-lang.svg)
![PyPI - License](https://img.shields.io/pypi/l/pycommons-lang)
![PyPI - Downloads](https://img.shields.io/pypi/dw/pycommons-lang)

[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

Python Commons Lang package inspired by [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/)
available in Java. Along with the utilities, mirroring Apache Commons Lang, this
library also provides additional language features borrowed from Java that can be used in Python like
Streams, Consumer, Predicates, Optional etc.

Visit the [documentation](https://pycommons.github.io/pycommons-lang) to view
the usage of each and every class and feature provided by this library.

## Get Started

To get started with this library, you can install this in your virtual environment
by running

```shell
pip install pycommons-lang
```

With [poetry](https://python-poetry.org/), you can run the following command to add the library to your
project

```shell
poetry add pycommons-lang
```

## License

Apache-2.0 (See [License](LICENSE))

## Author

[Shashank Sharma](https://github.com/shashankrnr32).

2 changes: 1 addition & 1 deletion docs/package/.pages
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
nav:
- StringUtils: StringUtils.md
- ...

title: Package Documentation
4 changes: 4 additions & 0 deletions docs/package/base/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- char: char.md

title: pycommons.lang.base
1 change: 1 addition & 0 deletions docs/package/base/char.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: pycommons.lang.base.char
4 changes: 4 additions & 0 deletions docs/package/container/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- optional: optional.md

title: pycommons.lang.container
1 change: 1 addition & 0 deletions docs/package/container/optional.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: pycommons.lang.container.optional
1 change: 0 additions & 1 deletion docs/package/stringutils.md

This file was deleted.

4 changes: 4 additions & 0 deletions docs/package/utils/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- stringutils: stringutils.md

title: pycommons.lang.utils
1 change: 1 addition & 0 deletions docs/package/utils/stringutils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: pycommons.lang.utils.stringutils
7 changes: 0 additions & 7 deletions pycommons/lang/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@

from importlib_metadata import PackageNotFoundError, version

from .arrayutils import ArrayUtils
from .charutils import CharUtils
from .objectutils import ObjectUtils
from .stringutils import StringUtils

__all__ = ["ArrayUtils", "CharUtils", "ObjectUtils"]

__author__ = "Shashank Sharma"
__email__ = "shashankrnr32@gmail.com"

Expand Down
File renamed without changes.
63 changes: 59 additions & 4 deletions pycommons/lang/bases/char.py → pycommons/lang/base/char.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ class Char(int):
"""
Defines a class to store a single character. Inherits `int` indicating, the value of
the character object holds the Unicode codepoint within the range (0, 65536). The class
mimics the methods provided by `str` like `isupper`, `isdigit` indicating the functionality
of the `Char` class is similar to that of a String.
mimics the methods provided by
[`str`](https://docs.python.org/3/library/stdtypes.html#string-methods) like
[`isupper`][pycommons.lang.base.char.Char.isupper],
[`isdigit`][pycommons.lang.base.char.Char.isdigit]
indicating the functionality of the `Char` class is similar to that of a String.

References:
https://docs.python.org/3/library/stdtypes.html#string-methods
"""

def __new__(cls, c: CharType) -> Char:
Expand Down Expand Up @@ -71,7 +77,8 @@ def isupper(self) -> bool:
Determines if the character is an uppercase letter, by converting the code point to
str object.

Returns: True if the character is an uppercase letter, False otherwise
Returns:
True if the character is an uppercase letter, False otherwise
"""
return chr(int(self)).isupper()

Expand All @@ -80,20 +87,68 @@ def islower(self) -> bool:
Determines if the character is a lowercase letter, by converting the code point to
str object.

Returns: True if the character is a lowercase letter, False otherwise
Returns:
True if the character is a lowercase letter, False otherwise
"""
return chr(int(self)).islower()

def isalpha(self) -> bool:
"""
Determines if the character is an alphabet, by converting the code point to str object.
Mimics the [isalpha](https://docs.python.org/3/library/stdtypes.html#str.isalpha) method
provided by str class in Python standard library.

Returns:
True if the character is an alphabet, False otherwise

References:
https://docs.python.org/3/library/stdtypes.html#str.isalpha
"""
return chr(int(self)).isalpha()

def isalnum(self) -> bool:
"""
Determines if the character is an alphabet or a digit,
by converting the code point to str object. Mimics the
[isalnum](https://docs.python.org/3/library/stdtypes.html#str.isalnum) method
provided by str class in Python standard library.

Returns:
True if the character is an alphabet or a digit, False otherwise

References:
https://docs.python.org/3/library/stdtypes.html#str.isalnum
"""
return chr(int(self)).isalnum()

def isascii(self) -> bool:
"""
Determines if the codepoint is in the range (0, 128), i.e. a valid ASCII character by
converting the code point to str object. ASCII characters have code
points in the range U+0000-U+007F. Mimics the
[isascii](https://docs.python.org/3/library/stdtypes.html#str.isascii) method
provided by str class of the Python standard library

Returns:
True if the character is a valid ASCII character, False otherwise

References:
https://docs.python.org/3/library/stdtypes.html#str.isascii
"""
return chr(int(self)).isascii()

def isdigit(self) -> bool:
"""
Determines if the character is a digit, by converting the code point to str object.
Mimics the [isascii](https://docs.python.org/3/library/stdtypes.html#str.isdigit) method
provided by str class of the Python standard library

Returns:
True if the character is a digit, False otherwise

References:
https://docs.python.org/3/library/stdtypes.html#str.isdigit
"""
return chr(int(self)).isdigit()

def isspace(self) -> bool:
Expand Down
42 changes: 41 additions & 1 deletion pycommons/lang/container/optional.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pycommons.lang.function.predicate import Predicate
from pycommons.lang.function.runnable import Runnable
from pycommons.lang.function.supplier import Supplier
from pycommons.lang.objectutils import ObjectUtils
from pycommons.lang.utils.objectutils import ObjectUtils

_T = TypeVar("_T", Any, None)
_U = TypeVar("_U", Any, None)
Expand All @@ -30,22 +30,62 @@ def __init__(self, value: Optional[_T]):
self._value = value

def get(self) -> _T:
"""
Gets the value in the container

Returns:
the value if present

Raises:
NoSuchElementError if the value is not present.

"""
if self._value is None:
raise NoSuchElementError("No value present")
return self._value

def is_present(self) -> bool:
"""
Returns True if a value is present in the container, False otherwise

Returns:
True if the container value is not None
"""
return self._value is not None

def is_empty(self) -> bool:
"""
Returns True if the container value is None, False otherwise

Returns:
True if the container value is None
"""
return not self.is_present()

def if_present(self, consumer: Consumer[_T]) -> None:
"""
Run a consumer if the value is present.

Args:
consumer: Consumer Lambda

Returns:
None
"""
ObjectUtils.require_not_none(consumer)
if self.is_present():
consumer.accept(self._value)

def if_present_or_else(self, consumer: Consumer[_T], runnable: Runnable) -> None:
"""
Runs a consumer if the value is present, else runs the runnable
Args:
consumer: Consumer function that runs when value is present
runnable: Runnable function that runs when value is None

Returns:
None
"""
ObjectUtils.require_not_none(consumer)
if self.is_present():
consumer.accept(self._value)
Expand Down
2 changes: 1 addition & 1 deletion pycommons/lang/function/predicate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from abc import abstractmethod
from typing import TypeVar, Generic, Callable, Any

from pycommons.lang.objectutils import ObjectUtils
from pycommons.lang.utils.objectutils import ObjectUtils

_T = TypeVar("_T")

Expand Down
Empty file.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import string
from typing import Optional, Set

from .bases.char import Char, CharType
from pycommons.lang.base.char import Char, CharType


class CharUtils:
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import typing
from typing import Optional, List

from pycommons.lang.base.char import Char
from pycommons.lang.function import Supplier
from .arrayutils import ArrayUtils
from .bases.char import Char
from .charutils import CharUtils
from .function import Supplier
from .utils import UtilityClass


class StringUtils:
class StringUtils(UtilityClass):
"""
The StringUtils `UtilityClass` that holds the utility methods for string observation,
manipulation, conversion etc. This class is inspired by the
[`StringUtils`](https://commons.apache.org/proper/commons-lang/apidocs/index.html)
class in the Apache Commons Lang package. Provides `None` safe methods to perform operations on
`str` object

References:
https://commons.apache.org/proper/commons-lang/apidocs/index.html
"""

EMPTY: str = ""

@classmethod
Expand Down
3 changes: 3 additions & 0 deletions pycommons/lang/utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class UtilityClass:
def __init__(self) -> None:
raise ValueError("A utility class cannot be instantiated")
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ max-locals = 20
min-public-method = 0

[tool.pytest.ini_options]
addopts = "--cov=pycommons --cov-branch --cov-report term-missing --cov-report xml -vv --color=yes --cov-fail-under 20"
addopts = "--cov=pycommons --cov-branch --cov-report term-missing --cov-report xml -vv --color=yes --cov-fail-under 5"
python_files = "tests.py test_*.py *_tests.py *Test.py"

[build-system]
Expand All @@ -71,3 +71,4 @@ test = "pytest"
lint = "pylint pycommons/ tests/"
black = "black ."
mypy = "mypy --strict --config-file=mypy.ini pycommons/"
docs = "mkdocs serve"
2 changes: 1 addition & 1 deletion tests/pycommons/lang/char_tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from unittest import TestCase

from pycommons.lang.bases import Char
from pycommons.lang.base import Char


class CharTest(TestCase):
Expand Down
4 changes: 2 additions & 2 deletions tests/pycommons/lang/charutils_tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest import TestCase

from pycommons.lang import CharUtils
from pycommons.lang.bases import Char
from pycommons.lang.base import Char
from pycommons.lang.utils.charutils import CharUtils


class CharUtilsTest(TestCase):
Expand Down