[](https://github.com/ccdale/ccautils/actions?workflow=Tests)
[](https://codecov.io/gh/ccdale/ccautils)
[](https://pypi.org/project/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: )