Metadata-Version: 2.1
Name: ccautils
Version: 0.4.2
Summary: A set of useful utilities for python programs
Home-page: https://github.com/ccdale/ccautils
License: GPL-3.0-or-later
Author: ccdale
Author-email: chris.charles.allison+ccautils@gmail.com
Requires-Python: >=3.6,<4.0
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Requires-Dist: python-dateutil (>=2.8.1,<3.0.0)
Requires-Dist: toml (>=0.10.0,<0.11.0)
Project-URL: Repository, https://github.com/ccdale/ccautils
Description-Content-Type: text/markdown

[![Tests](https://github.com/ccdale/ccautils/workflows/Tests/badge.svg)](https://github.com/ccdale/ccautils/actions?workflow=Tests)
[![Codecov](https://codecov.io/gh/ccdale/ccautils/branch/master/graph/badge.svg)](https://codecov.io/gh/ccdale/ccautils)
[![Python](https://img.shields.io/pypi/pyversions/ccautils)](https://pypi.org/project/ccautils/)
[![PyPI](https://img.shields.io/pypi/v/ccautils)](https://pypi.org/project/ccautils/)
# ccautils

a set of utilities for python3.6+ programs and scripts.

<a name=headdd></a>
* [Install](#install)
* [Development](#devel)
* [Testing](#testing)
* [Error Utilities](#errors)
* [Miscellaneous Utilities](#utils)
    * [Usage](#uusage)
* [File Utilities](#futils)
    * [Usage](#fusage)


<a name=install></a>
## [Install](#headdd)

Install for the user:
```
pip3 install ccautils --user
```

Install for a virtual environment:
```
pip install ccautils
```

<a name=devel></a>
## [Development](#headdd)

I use [poetry](https://python-poetry.org/) to manage these utilities.
Clone this repository and install `poetry`, then install the dependancies.

```
git clone https://github.com/ccdale/ccautils.git
cd ccautils
poetry install
```

<a name=testing></a>
## [Testing](#headdd)
To run the tests you must have `pytest`, `nox` and `poetry` installed.

install nox into your python user environment.
```
pip install nox --user
```

Run the tests with

```
nox -rs tests
```

Run the linter with

```
nox -rs lint
```

Run the console ask tests with

```
nox -rs tests -- -sm ask
```

<a name=errors></a>
## Error Utilities(#headdd)

See the [code](https://github.com/ccdale/ccautils) for how to use these
Exception helpers.


<a name=utils></a>
## [Miscellaneous Utilities](#headdd)

<a name=uusage></a>
### [Usage](#headdd)

```
import ccautils.utils as UT
```

<a name=menu></a>
* [addToString](#addtostring)
* [delimitString](#delimitstring)
* [makeDictFromString](#makedictfromstring)
* [askMe](#askme)
* [padStr](#padstr)
* [reduceTime](#reducetime)
* [displayValue](#displayvalue)
* [secondsFromHMS](#secondsfromhms)
* [hms](#hms)

<a name=addtostring></a>
### [addToString(xstr, xadd)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L26)

Returns a string with `xadd` appended to `xstr`.  If `xadd` is a list, all
`str` members of the list will be appended in order.

```
UT.addToString("hello", [" ", "world"])

> "hello world"
```

<a name=delimitstring></a>
### [delimitString(xstr, delimeter=" - ")](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L49)

`xstr` can be a list or a string.  If it is a string, it is spit apart at
spaces and delimeted with `delimeter`.  If it is a list, each member is
delimeted with `delimeter`.

```
UT.delimitString(["bright", "world"], " ")

> "bright world"

UT.delimitString("I wandered lonely as an artichoke", ".")

> "I.wandered.lonely.as.an.artichoke"
```

<a name=makedictfromstring></a>
### [makeDictFromString(istr)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L64)

Constructs a dictionary from a string of parameters. Leading and trailing
whitespace is stripped.

`istr` should be in the form `someparam=somevalue,someotherparam=otherval`

```
UT.makeDictFromString("sparam=sval, soparam = soval")

> {"sparam": "sval", "soparam": "soval"}
```

<a name=askme></a>
### [askMe(q, default)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L89)

Requests input from the user.  Poses the question `q`. Returns the users
input or `default` if no input given.

```
UT.askMe("press 5, please", "8")

> press 5, please: 5
> 5
```

<a name=padstr></a>
### [padStr(xstr, xlen=2, pad=" ", padleft=True)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L101)

Returns `xstr` `pad`ded to the required length, either on the
left (`padleft` is True) or the right (`padleft` is False)

```
UT.padStr("23", 5, "0")

> "00023"
```

<a name=reducetime></a>
### [reduceTime(unit, secs)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L115)

Divides `secs` by `unit` returning a tuple of (`units`, `remainder`)

Raises a `ValueError` if `unit` is zero.

```
UT.reduceTime(3600, 3700)

> (1, 100)
```

<a name=displayvalue></a>
### [displayValue(val, label, zero=True)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L131)

Pluralises `label` if `val` > 1 or `val` is 0.

Will return an empty string if `val` == 0 and `zero` == True

```
UT.displayValue(12, "table")

> "12 tables"
```

<a name=secondsfromhms></a>
### [secondsFromHMS(shms)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L142)

converts HMS strings into integer seconds

```
UT.secondsFromHMS("01:01:23.43")
# 1 hour, 1 minute, 23 seconds + 0.43 second

> 3683
```

<a name=hms></a>
### [hms(secs, small=True, short=True, single=False, colons=False)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L214)

Convert `secs` to days, hours, minutes and seconds

if `small` is True then only return the higher values if they are > zero

if `short` is True then the labels are their short form

if `single` is True then the labels are single letters

if `colons` is True then the output is of the form `01:03:23`

```
UT.hms(67)

> "1 min and 7 secs"

UT.hms(67, short=False)

> "1 minute and 7 seconds"

UT.hms(67, small=False, short=False)

> "0 days, 0 hours, 1 minute and 7 seconds"

secs = 86400 + 7200 + 300 + 34
UT.hms(secs, single=True)

> "1d 2h 5m 34s"

secs = 345
UT.hms(secs, colons=True)

> "05:45"

secs = 86400 + 7200 + 300 + 34
UT.hms(secs, colons=True)

> "01:02:05:34"
```

<a name=fuzzyexpires></a>
### [fuzzyExpires(dt)](#menu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/utils.py#L381)

Given a `datetime` object, computes the difference between now and that
time.  Returns a tuple of (`ts`: unix timestamp of `dt`, `op`: string)

The returned string gives the approximate time left between now and the
`dt` object or the string 'EXPIRED'.

```

    """It returns 2 hours 20 minutes and some seconds."""
    ts = int(time.time())
    ts += (3600 * 2) + (60 * 20)
    dt = datetime.datetime.fromtimestamp(ts)
    gotts, gotstr = UT.fuzzyExpires(dt)


    """It returns 1 year and 2 months."""
    ts = int(time.time())
    ts += (86400 * 365) + (86400 * 70)
    dt = datetime.datetime.fromtimestamp(ts)
    gotts, gotstr = UT.fuzzyExpires(dt)
```

<a name=futils></a>
## [File Utilities](#headdd)

<a name=fusage></a>
### [Usage](#headdd)

```
import ccautils.fileutils as FT
```

<a name=fmenu></a>
* [fileExists](#fileexists)
* [dirExists](#direxists)
* [dfExists](#dfexists)
* [makePath](#makepath)

<a name=fileexists></a>
### [fileExists(fqfn)](#fmenu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/fileutils.py#L30)

Tests for the existence of the fully-qualified (absolute) file name `fqfn`

Returns: `True` if `fqfn` exists, else `False`

```
fn = "/home/chris/output.csv"
if FT.fileExists(fn):
    # do something
else:
    raise(f"File {fn} does not exist")
```

<a name=direxists></a>
### [dirExists(fqdn)](#fmenu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/fileutils.py#L38)

Tests for the existence of the fully-qualified (absolute) directory name `fqdn`

Returns: `True` if `fqdn` exists, else `False`

```
dn = "/home/chris"
if FT.dirExists(dn):
    # do something
else:
    raise(f"Directory {dn} does not exist")
```

<a name=dfexists></a>
### [dfExists(fqdfn)](#fmenu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/fileutils.py#L46)

Tests to see if the file `fqdfn` exists, if not checks if `fqdfn` is
a directory that exists.

Returns: `True` if `fqdfn` exists, else `False`

```
dn = "/home/chris"
if FT.dfExists(dn):
    # do something
else:
    raise(f"File / Directory {dn} does not exist")
```

<a name=makepath></a>
### [makePath(pn)](#fmenu)

[Code](https://github.com/ccdale/ccautils/blob/master/ccautils/fileutils.py#L57)

Makes the path `pn` including any missing parent directories.  Does
nothing if path `pn` already exists.

Returns: None
```
dn = "/home/chris/appdir/subdir"
FT.makePath(dn)
```


[modeline]: # ( vim: set ft=markdown tw=74 fenc=utf-8 spell spl=en_gb mousemodel=popup: )

