Browse Source

Merge branch 'master' of gitea:gmj/home.public.snippits

George Jones 1 year ago
parent
commit
db0621f401

+ 12 - 0
home/public/snippits/X/set-x-title.sh

@@ -0,0 +1,12 @@
+function set_xtitle {
+    # set X window title
+    #
+    # Usage:
+    #
+    #   set_xtitle [name]
+    WINDOW_NAME="${1:-`basename $PWD`}"
+    PROMPT_COMMAND="echo -ne \"\033]0;${WINDOW_NAME} $USER@$HOSTNAME:$PWD\007\"";
+}
+
+
+export PROMPT_COMMAND="history -a; history -c; history -r; set_xtitle"

+ 4 - 2
home/public/snippits/bash/bashArrays.sh

@@ -28,8 +28,10 @@
 
 #
 # http://www.linuxjournal.com/content/return-values-bash-functions
-# 
-
+#
+# Also see, c.a. 2022-10-18, very helpful
+#
+#   https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays
 
 
 source bashUtils.sh

+ 1 - 0
home/public/snippits/bash/bashGetopt.sh

@@ -10,6 +10,7 @@
 
 #   
  
+
 OPTS=`getopt -o vhns: --long verbose,dry-run,help,stack-size: -n 'parse-options' -- "$@"`
  
 if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

+ 71 - 0
home/public/snippits/bash/function-template.sh

@@ -0,0 +1,71 @@
+# This is my bash function template.  
+#
+# Usage:
+#   source THISFILE
+
+#   example		# print help
+#   example --help      # print help
+#   example foo         # run with one arg
+#   example foo bar     # run with two args
+
+#
+#
+source $HOME/lib/bash/bashutils.sh  # error,warning,...
+
+ARGV=("$@")
+ARGC=("$#")
+
+
+function example() ( # function in subshell, own namespece.
+
+    ARG1="${1:-NONE}"
+    ARG2="${2:-NONE}"
+
+    function usage ()  {
+
+        message=${1:-""}
+
+        cat <<EOF 1>&2
+Usage: $0 [options] ARG1 [ARG2]
+
+EXAMPLE does this..
+
+-h| --help           print help text
+
+ARG1                 This argument (required) does..
+ARG2                 This argument (optional) does...
+
+Examples:
+  example thing1
+  example thing1 thing2
+  example --help
+EOF
+
+
+        if [[ "${message}" != "" ]]; then
+           echo 2>&1
+           error "${message}"
+        fi
+    }
+
+    case $ARG1 in
+        NONE)		usage "Missing ARG1" && return 1;;
+        -d|--debug)	DEBUG=1 && shift;;
+        -h|--help)	usage && return 1;;
+    esac
+
+
+    if [ "$ARG2" == "NONE" ]; then
+       info "ARG2 not defined"
+    else
+        echo # do something with ARG2
+    fi
+    
+    cmd="echo $ARG1 $ARG2"
+    debug "command: ${cmd}" # export DEBUG=1 for debugging
+    
+    [[ -v DEBUG ]] && set -x
+
+    echo args are $* || warn "something went wrong"
+
+)

+ 39 - 0
home/public/snippits/bash/functions-as-subshells.sh

@@ -0,0 +1,39 @@
+# https://cuddly-octo-palm-tree.com/posts/2021-10-31-better-bash-functions/
+f() (
+    # code
+    var1=${1:-"default"}
+
+    
+    if [ "${var1}" == "default" ]; then
+        #echo errors and warning messages to stderr 1>&2
+        return 1 # error, outut undefined
+    fi
+
+    echo "StirngValueOnSTDOUT"
+    return 0 # success, output defined
+)
+
+
+return=`f` && echo SUCCESS return value is $return  || echo FAILURE no return
+echo
+
+return=`f FOO` && echo SUCCESS return value is $return  || echo FAILURE no return
+echo
+
+if retval=f; then
+    echo f with no argument succeeded
+else
+    echo f with no argument failed
+fi
+
+if retval=`f BAR`; then
+    echo f with an argument succeeded and retval is $retval
+else
+    echo f with an argument failed
+fi
+
+if f BAR; then
+    echo f with an argument succeeded, ignoring retval
+else
+    echo f with an argument failed
+fi

+ 56 - 0
home/public/snippits/bash/indirs.sh

@@ -0,0 +1,56 @@
+#! /bin/bash
+
+
+source $HOME/lib/bash/bashutils.sh  # error,warning,...
+
+indirs ()
+# return "true" if there is a directory in the stack that contains "$1"
+(
+    
+    CONTAINS="${1:-NONE}"
+
+    if [ "$CONTAINS" == "NONE" ]; then
+        warn "no directory name given for indirs"
+        return $FALSE
+    fi
+    
+    for d in `dirs`;
+    do
+        if [[ "$d" == *"${CONTAINS}"* ]]; then
+            return $TRUE
+        fi
+    done
+
+    info ${CONTAINS} not found in dirs
+    return $FALSE
+)
+
+p2 ()
+# pop to (p2) a directory in the directory stack that contains P2THIS
+{
+    
+    P2THIS="${1:-NONE}"
+
+    if [ "$P2THIS" == "NONE" ]; then
+        warn "no directory name given for p2"
+        return $FALSE
+    fi
+
+    if indirs $P2THIS; then
+
+        # pop until $PWD ends with $P2THIS
+        while true;
+        do
+            if [[ "$PWD" == *"${P2THIS}"* ]]; then
+                dirs
+                return $TRUE
+            else
+                popd 1> /dev/null || return $FALSE
+            fi
+        done
+
+    else
+        echo $INDIRS not found in `dirs`
+    fi
+}
+

+ 10 - 0
home/public/snippits/bash/utils-template.sh

@@ -0,0 +1,10 @@
+# include my helper funcs or define simple versions inline
+if [ -f $HOME/lib/bash/bashutils.sh ]; then
+    source $HOME/lib/bash/bashutils.sh
+else
+    function info()  { echo `date +%c` \: info: "$@" 1>&2; }
+    function warn()  { echo `date +%c` \: warning: "$@" 1>&2; }
+    function error() { echo `date +%c` \: error: "$@" 1>&2; }
+    function debug() { [[ -v DEBUG ]] && echo `date +%c` \: debug: "$@" 1>&2 || true ; }
+    function die()   { echo `date +%c` \: fatal: "$@" 1>&2 && exit 1; }
+fi

+ 29 - 0
home/public/snippits/pandas/filter_df_by_regex.py

@@ -0,0 +1,29 @@
+#! /usr/bin/env python3
+# filter dataframe by matching regex
+
+# https://stackoverflow.com/questions/37080612/pandas-dataframe-filter-regex/37080814#37080814
+
+import pandas as pd
+data = {
+    'Company' : ['Ford','Ford','Ford','Ford','Chevy','Chevy'],
+    'Type' : ['Mercury','Lincoln','Lincoln','Econoline','Malabu','Pickups'],
+    'Profit' : [1,100,40,99,2,3]
+}
+df = pd.DataFrame(data)
+
+# print(df)
+
+#   Company       Type  Profit
+# 0    Ford    Mercury       1
+# 1    Ford    Lincoln     100
+# 2    Ford    Lincoln      40
+# 3    Ford  Econoline      99
+# 4   Chevy     Malabu       2
+# 5   Chevy    Pickups       3
+
+# Now print only rows that have an "e" in the Type
+# preceeded by a capitol letter or has a "u"
+#
+# That's how I choose# my cars :-)
+
+print(df[df["Type"].str.contains('[A-Z]e|u',regex=True)])

+ 4 - 0
home/public/snippits/pandas/foo.csv

@@ -0,0 +1,4 @@
+foo,bar,baz
+# This is a comment, ignore it.
+1,2,3
+4,5,6

+ 25 - 0
home/public/snippits/pandas/group_and_count.py

@@ -0,0 +1,25 @@
+#! /usr/bin/env python3
+# playing with group and count
+
+# https://stackoverflow.com/questions/38174155/group-dataframe-and-get-sum-and-count
+
+
+import pandas as pd
+data = {
+    'Company' : ['Ford','Ford','Ford','Ford','Chevy','Chevy'],
+    'Type' : ['Mercury','Lincoln','Lincoln','Econoline','Malabu','Pickups'],
+    'Profit' : [1,100,40,99,2,3]
+}
+df = pd.DataFrame(data)
+
+# Want to compute mean and std of Profit
+# Add duplicates of value to be aggrigated
+df['mean_profit'] = df["Profit"]
+df['std_profit'] = df["Profit"]
+
+df2 = df.groupby('Company').agg({'Type':'count','Profit':'sum', 'mean_profit':'mean','std_profit':'std'}).reset_index().rename(columns={'Type':"count"})
+print(df2)
+
+#   Company  count  Profit  mean_profit  std_profit
+# 0   Chevy      2       5          2.5    0.707107
+# 1    Ford      4     240         60.0   48.311489

+ 32 - 0
home/public/snippits/pandas/move_rows.py

@@ -0,0 +1,32 @@
+# Move rows from one dataframe to another
+# https://stackoverflow.com/questions/36142959/pandas-move-rows-from-1-df-to-another-df#36143395
+
+import pandas as pd
+
+data = {'Name':['Tom', 'nick', 'krish', 'jack'], 'Age':[20, 21, 19, 18]}
+df = pd.DataFrame(data)
+
+df_from = df.copy()
+df_to = pd.DataFrame()
+
+def move(a,b,cond):
+
+    rows = a.loc[cond, :]
+
+    # b.append acts like pass-by-value, parent not affected
+    b = b.append(rows, ignore_index=True)
+
+    # a.drop acts like pass-by-reference, parent affected
+    a.drop(rows.index, inplace=True)
+    return b
+
+    # return local copy so it can be assigned in parent
+    return(b)
+
+df_to = move(df_from,df_to,df_from.Name == "Tom")
+df_to = move(df_from,df_to,df_from.Name == "nick")
+print("AFTER")
+print(f"df_from is {df_from}")
+print(f"df_to is {df_to}")
+print()
+

+ 7 - 0
home/public/snippits/pandas/read_csv.py

@@ -0,0 +1,7 @@
+#! /usr/bin/env python3
+# Read a CSV file and ignore comments,  read everything as a string
+
+import pandas as pd
+
+df = pd.read_csv("foo.csv",comment='#',dtype=str)
+print(df)

+ 27 - 0
home/public/snippits/python/dates.py

@@ -0,0 +1,27 @@
+#! /usr/bin/env python
+# Date manipulation examples
+
+# https://datagy.io/python-string-to-date/
+# https://stackoverflow.com/questions/12566152/python-x-days-ago-to-datetime
+
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+
+
+date_string = '2021-12-31'
+then = datetime.strptime(date_string, '%Y-%m-%d')
+print(f"then: {then}")
+
+now = datetime.now()
+print(f"now: {now}")
+
+diff = now - then
+print(diff)
+
+# minus 1 year
+
+oneYearAgoDate = datetime.now() - relativedelta(years=1)
+
+oneYearAgoString = oneYearAgoDate.strftime('%Y-%m-%d')
+
+print(oneYearAgoString)

+ 66 - 0
home/public/snippits/python/docstrings.py

@@ -0,0 +1,66 @@
+# Docstirng examles from https://realpython.com/documenting-python-code/
+class Animal:
+    """
+    A class used to represent an Animal
+
+    ...
+
+    Attributes
+    ----------
+    says_str : str
+        a formatted string to print out what the animal says
+    name : str
+        the name of the animal
+    sound : str
+        the sound that the animal makes
+    num_legs : int
+        the number of legs the animal has (default 4)
+
+    Methods
+    -------
+    says(sound=None)
+        Prints the animals name and what sound it makes
+    """
+
+    says_str = "A {name} says {sound}"
+
+    def __init__(self, name, sound, num_legs=4):
+        """
+        Parameters
+        ----------
+        name : str
+            The name of the animal
+        sound : str
+            The sound the animal makes
+        num_legs : int, optional
+            The number of legs the animal (default is 4)
+        """
+
+        self.name = name
+        self.sound = sound
+        self.num_legs = num_legs
+
+    def says(self, sound=None):
+        """Prints what the animals name is and what sound it makes.
+
+        If the argument `sound` isn't passed in, the default Animal
+        sound is used.
+
+        Parameters
+        ----------
+        sound : str, optional
+            The sound the animal makes (default is None)
+
+        Raises
+        ------
+        NotImplementedError
+            If no sound is set for the animal or passed in as a
+            parameter.
+        """
+
+        if self.sound is None and sound is None:
+            raise NotImplementedError("Silent Animals are not supported!")
+
+        out_sound = self.sound if sound is None else sound
+        print(self.says_str.format(name=self.name, sound=out_sound))
+

+ 310 - 0
home/public/snippits/python/example_google.py

@@ -0,0 +1,310 @@
+"""Example Google style docstrings.  FROM: https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html#example-google  2022-10-14
+
+This module demonstrates documentation as specified by the `Google Python
+Style Guide`_. Docstrings may extend over multiple lines. Sections are created
+with a section header and a colon followed by a block of indented text.
+
+Example:
+    Examples can be given using either the ``Example`` or ``Examples``
+    sections. Sections support any reStructuredText formatting, including
+    literal blocks::
+
+        $ python example_google.py
+
+Section breaks are created by resuming unindented text. Section breaks
+are also implicitly created anytime a new section starts.
+
+Attributes:
+    module_level_variable1 (int): Module level variables may be documented in
+        either the ``Attributes`` section of the module docstring, or in an
+        inline docstring immediately following the variable.
+
+        Either form is acceptable, but the two should not be mixed. Choose
+        one convention to document module level variables and be consistent
+        with it.
+
+Todo:
+    * For module TODOs
+    * You have to also use ``sphinx.ext.todo`` extension
+
+.. _Google Python Style Guide:
+   https://google.github.io/styleguide/pyguide.html
+
+"""
+
+module_level_variable1 = 12345
+
+module_level_variable2 = 98765
+"""int: Module level variable documented inline.
+
+The docstring may span multiple lines. The type may optionally be specified
+on the first line, separated by a colon.
+"""
+
+
+def function_with_types_in_docstring(param1, param2):
+    """Example function with types documented in the docstring.
+
+    :pep:`484` type annotations are supported. If attribute, parameter, and
+    return types are annotated according to `PEP 484`_, they do not need to be
+    included in the docstring:
+
+    Args:
+        param1 (int): The first parameter.
+        param2 (str): The second parameter.
+
+    Returns:
+        bool: The return value. True for success, False otherwise.
+    """
+
+
+def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
+    """Example function with PEP 484 type annotations.
+
+    Args:
+        param1: The first parameter.
+        param2: The second parameter.
+
+    Returns:
+        The return value. True for success, False otherwise.
+
+    """
+
+
+def module_level_function(param1, param2=None, *args, **kwargs):
+    """This is an example of a module level function.
+
+    Function parameters should be documented in the ``Args`` section. The name
+    of each parameter is required. The type and description of each parameter
+    is optional, but should be included if not obvious.
+
+    If ``*args`` or ``**kwargs`` are accepted,
+    they should be listed as ``*args`` and ``**kwargs``.
+
+    The format for a parameter is::
+
+        name (type): description
+            The description may span multiple lines. Following
+            lines should be indented. The "(type)" is optional.
+
+            Multiple paragraphs are supported in parameter
+            descriptions.
+
+    Args:
+        param1 (int): The first parameter.
+        param2 (:obj:`str`, optional): The second parameter. Defaults to None.
+            Second line of description should be indented.
+        *args: Variable length argument list.
+        **kwargs: Arbitrary keyword arguments.
+
+    Returns:
+        bool: True if successful, False otherwise.
+
+        The return type is optional and may be specified at the beginning of
+        the ``Returns`` section followed by a colon.
+
+        The ``Returns`` section may span multiple lines and paragraphs.
+        Following lines should be indented to match the first line.
+
+        The ``Returns`` section supports any reStructuredText formatting,
+        including literal blocks::
+
+            {
+                'param1': param1,
+                'param2': param2
+            }
+
+    Raises:
+        AttributeError: The ``Raises`` section is a list of all exceptions
+            that are relevant to the interface.
+        ValueError: If `param2` is equal to `param1`.
+
+    """
+    if param1 == param2:
+        raise ValueError('param1 may not be equal to param2')
+    return True
+
+
+def example_generator(n):
+    """Generators have a ``Yields`` section instead of a ``Returns`` section.
+
+    Args:
+        n (int): The upper limit of the range to generate, from 0 to `n` - 1.
+
+    Yields:
+        int: The next number in the range of 0 to `n` - 1.
+
+    Examples:
+        Examples should be written in doctest format, and should illustrate how
+        to use the function.
+
+        >>> print([i for i in example_generator(4)])
+        [0, 1, 2, 3]
+
+    """
+    for i in range(n):
+        yield i
+
+
+class ExampleError(Exception):
+    """Exceptions are documented in the same way as classes.
+
+    The __init__ method may be documented in either the class level
+    docstring, or as a docstring on the __init__ method itself.
+
+    Either form is acceptable, but the two should not be mixed. Choose one
+    convention to document the __init__ method and be consistent with it.
+
+    Note:
+        Do not include the `self` parameter in the ``Args`` section.
+
+    Args:
+        msg (str): Human readable string describing the exception.
+        code (:obj:`int`, optional): Error code.
+
+    Attributes:
+        msg (str): Human readable string describing the exception.
+        code (int): Exception error code.
+
+    """
+
+    def __init__(self, msg, code):
+        self.msg = msg
+        self.code = code
+
+
+class ExampleClass:
+    """The summary line for a class docstring should fit on one line.
+
+    If the class has public attributes, they may be documented here
+    in an ``Attributes`` section and follow the same formatting as a
+    function's ``Args`` section. Alternatively, attributes may be documented
+    inline with the attribute's declaration (see __init__ method below).
+
+    Properties created with the ``@property`` decorator should be documented
+    in the property's getter method.
+
+    Attributes:
+        attr1 (str): Description of `attr1`.
+        attr2 (:obj:`int`, optional): Description of `attr2`.
+
+    """
+
+    def __init__(self, param1, param2, param3):
+        """Example of docstring on the __init__ method.
+
+        The __init__ method may be documented in either the class level
+        docstring, or as a docstring on the __init__ method itself.
+
+        Either form is acceptable, but the two should not be mixed. Choose one
+        convention to document the __init__ method and be consistent with it.
+
+        Note:
+            Do not include the `self` parameter in the ``Args`` section.
+
+        Args:
+            param1 (str): Description of `param1`.
+            param2 (:obj:`int`, optional): Description of `param2`. Multiple
+                lines are supported.
+            param3 (list(str)): Description of `param3`.
+
+        """
+        self.attr1 = param1
+        self.attr2 = param2
+        self.attr3 = param3  #: Doc comment *inline* with attribute
+
+        #: list(str): Doc comment *before* attribute, with type specified
+        self.attr4 = ['attr4']
+
+        self.attr5 = None
+        """str: Docstring *after* attribute, with type specified."""
+
+    @property
+    def readonly_property(self):
+        """str: Properties should be documented in their getter method."""
+        return 'readonly_property'
+
+    @property
+    def readwrite_property(self):
+        """list(str): Properties with both a getter and setter
+        should only be documented in their getter method.
+
+        If the setter method contains notable behavior, it should be
+        mentioned here.
+        """
+        return ['readwrite_property']
+
+    @readwrite_property.setter
+    def readwrite_property(self, value):
+        value
+
+    def example_method(self, param1, param2):
+        """Class methods are similar to regular functions.
+
+        Note:
+            Do not include the `self` parameter in the ``Args`` section.
+
+        Args:
+            param1: The first parameter.
+            param2: The second parameter.
+
+        Returns:
+            True if successful, False otherwise.
+
+        """
+        return True
+
+    def __special__(self):
+        """By default special members with docstrings are not included.
+
+        Special members are any methods or attributes that start with and
+        end with a double underscore. Any special member with a docstring
+        will be included in the output, if
+        ``napoleon_include_special_with_doc`` is set to True.
+
+        This behavior can be enabled by changing the following setting in
+        Sphinx's conf.py::
+
+            napoleon_include_special_with_doc = True
+
+        """
+        pass
+
+    def __special_without_docstring__(self):
+        pass
+
+    def _private(self):
+        """By default private members are not included.
+
+        Private members are any methods or attributes that start with an
+        underscore and are *not* special. By default they are not included
+        in the output.
+
+        This behavior can be changed such that private members *are* included
+        by changing the following setting in Sphinx's conf.py::
+
+            napoleon_include_private_with_doc = True
+
+        """
+        pass
+
+    def _private_without_docstring(self):
+        pass
+
+class ExamplePEP526Class:
+    """The summary line for a class docstring should fit on one line.
+
+    If the class has public attributes, they may be documented here
+    in an ``Attributes`` section and follow the same formatting as a
+    function's ``Args`` section. If ``napoleon_attr_annotations``
+    is True, types can be specified in the class body using ``PEP 526``
+    annotations.
+
+    Attributes:
+        attr1: Description of `attr1`.
+        attr2: Description of `attr2`.
+
+    """
+
+    attr1: str
+    attr2: int

+ 29 - 0
home/public/snippits/python/json_read_and_write.py

@@ -0,0 +1,29 @@
+#! /usr/bin/env python3
+# Write and read json files
+#
+# See https://www.geeksforgeeks.org/reading-and-writing-json-to-a-file-in-python/
+#
+
+import json
+
+# make a random dictionary
+foo_dict={}
+foo_dict["bar"] = "A bar"
+foo_dict["baz"] = "A baz"
+
+print(f"foo_dict: {foo_dict}")
+
+# create json a string
+foo_json = json.dumps(foo_dict,indent=4)
+
+print(f"foo_json: {foo_json}")
+
+# save it to a file
+with open("sample.json", "w") as outfile:
+    outfile.write(foo_json)
+
+# read it back
+with open('sample.json', 'r') as openfile:
+    bar_json = json.load(openfile)
+ 
+print(f"bar_json: {bar_json}")

+ 22 - 0
home/public/snippits/python/re_search.py

@@ -0,0 +1,22 @@
+#! /usr/bin/env python
+# Simple regex examples
+
+import re
+
+foo="The foo in bar falls in Maine, mainly"
+
+if re.search("foo",foo):
+    print(f"'foo' is in {foo}")
+else:
+    print(f"'foo' is NOT in {foo}")
+
+if re.search("bar",foo):
+    print(f"'bar' is in {foo}")
+else:
+    print(f"'bar' is NOT in {foo}")
+
+
+if re.search("^The",foo):
+    print(f"'The' is at the start of {foo}")
+else:
+    print(f"'The' is NOT at the start of {foo}")