{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1 style=\"text-align:center\">pyMez Module Specification</h1>\n",
    "\n",
    "<hr style=\"border-top: 3px double #8c8b8b;\"/>\n",
    "<ol style='list-style-type: upper-roman;'>\n",
    "<h2><li>Module Naming Convention </li></h2> \n",
    "Modules are named as UpperCamelCase (breaking from python tradition) \n",
    "<blockquote> GeneralModels </blockquote>\n",
    "<h2><li>Module Info and Docstring</li></h2> \n",
    " Module Info is a comment block  with stuff like your name and license. The Module Docstring is the first quoted string and should provide information about the module. It is my habit to keep docstrings to a paragraph with links for expanded examples and help documentation. For example:\n",
    " ```python\n",
    " \"\"\"\n",
    "Graph Models stores sub classes of graphs that define data translations. All edges\n",
    "or the functions that define translations from one format to another\n",
    "are found in <a href=\"./Translations.m.html\">`pyMez.Code.DataHandlers.Translations`</a>.\n",
    "Currently, the module networkx is used to display the graph.\n",
    "\n",
    "Examples\n",
    "--------\n",
    "    #!python\n",
    "    >>from pyMez import *\n",
    "    >>image_graph=ImageGraph()\n",
    "    >>image_graph.set_state('png','my_png.png')\n",
    "    >>image_graph.move_to_node('EmbeddedHtml')\n",
    "    >>output=image_graph.data\n",
    "    >>print output\n",
    "\n",
    "\n",
    "<a href=\"../../../Examples/Html/GraphModels_Example.html\">GraphModels Example</a>\n",
    "\n",
    "Requirements\n",
    "------------\n",
    "+ [sys](https://docs.python.org/2/library/sys.html)\n",
    "+ [os](https://docs.python.org/2/library/os.html?highlight=os#module-os)\n",
    "+ [networkx](http://networkx.github.io/)\n",
    "+ [numpy](http://www.numpy.org/)\n",
    "+ [pyMez](https://github.com/aricsanders/pyMez)\n",
    "\n",
    "Help\n",
    "---------------\n",
    "<a href=\"./index.html\">`pyMez.Code.DataHandlers`</a>\n",
    "<div>\n",
    "<a href=\"../../../pyMez_Documentation.html\">Documentation Home</a> |\n",
    "<a href=\"../../index.html\">API Documentation Home</a> |\n",
    "<a href=\"../../Examples/Html/Examples_Home.html\">Examples Home</a> |\n",
    "<a href=\"../../../Reference_Index.html\">Index</a>\n",
    "</div>\n",
    "   \"\"\"\n",
    "   ```\n",
    " <h2><li>Module Imports</li></h2> \n",
    " <ol style='list-style-type: upper-roman;'><li>Standard Imports</li> \n",
    " Imports that are in the standard library and should always work if you have python installed properly. They should be namspaced,\n",
    " ```python\n",
    "    import os\n",
    "  ```\n",
    " <li>3rd Party Imports</li> \t\t\n",
    " Imports from within the user defined package or other places that HAD to be loaded separately. These imports should have a try: except: structure. That is, if they fail the program should default to something useful. \n",
    "```python\n",
    "    try:\n",
    "        from Code.DataHandlers.GeneralModels import *\n",
    "    except:\n",
    "        print(\"The module pyMez.Code.DataHandlers.GeneralModels was not found,\"\n",
    "              \"please put it on the python path\")\n",
    "        raise  ImportError\n",
    "```\n",
    " <h2><li>Module Constants</li></h2> The constants that can be used through out the module. Constant names should be \tALL_UPPERCASE_WITH_UNDERSCORES.\n",
    "```python\n",
    "   S2P_COMPLEX_COLUMN_NAMES=[\"Frequency\",\"S11\",\"S21\",\"S12\",\"S22\"]\n",
    "   ```\n",
    "  <h2><li>Module Functions</li></h2> A module function takes a variable(s) and maps it to another variable(s). Function names \tshould be all_lowercase_with_underscores.\n",
    "  \n",
    "  ```python\n",
    "  def x_squared(x):\n",
    "  \"A function that maps x->x**2\"\n",
    "  return x**2```\n",
    "  \n",
    " <h2><li>Module Class Definitions</li></h2> \t\n",
    " A module class is a complex data container which can inherit functions (methods) and \tvariables (attributes) from other objects. They are the foundation of Object Oriented \tprogramming. Module names should be TitleCaseWithNoSpaces. Methods and attributes should   \tbe either all_lowercase_with_underscores or lowerThenTitleCaseWithNoSpaces. It is common \tfor me to define aliases for methods so that both MyClass.myMethod() and \tMyClass.my_method() work. \n",
    " \n",
    " ```python\n",
    "  class MyClass():\n",
    "  \"An empty class for demonstration\"\n",
    "  pass```\n",
    "  \n",
    "<h2><li>Module Scripts</li></h2> \t\tA module script is a function or procedure that does something and returns at most a boolean \tvalue. The reason they are not defined with module functions is so that they can use all of the \tclass definitions. The reason they are not only in the Module runner is so that they can be \taccessed by importing the module. I usually try to put one of the following words in the name:\n",
    "\ttest,script or robot and the name is all_lowercase_with_underscores.\n",
    " ```python\n",
    "    def test_f(x_test=2):\n",
    "    \"Tests the function f\"\n",
    "    print(\"The Result of f({0}) is {1}\".format(x_test,f(x_test)))```\n",
    "      \n",
    "<h2><li>Module Runner</li></h2> \t\tThe statement ```if __name__ == '__main__': ``` at the end of the module determines the module's behavior if it is opened as a file or ran from a shell prompt as \n",
    "`$python ModuleName.py`. \n",
    "\n",
    "I usually just call module script(s) of interest here.\n",
    "\n",
    "  ```python\n",
    "  if __name__=='__main__':\n",
    "  test_f()```\n",
    "\n",
    "</ol>\n",
    "__Notes:__<hr/>\n",
    "There are several exceptions to the naming rules\n",
    "1. The word py in my code is always lowercase\n",
    "2. The words HTML and XML are always capitalized\n",
    "3. If there is a case sensitive quantity in the name of a function it has it's original case get_Id() \n",
    "<hr/>\n",
    "1. Avoid relative imports such as from . import a,  instead inject a folder above it into sys.path and import the module using the full name space, this keeps the module from breaking when called as a script. \n",
    "```python\n",
    "sys.path.append(os.path.join(os.path.dirname( __file__ ), '..','..'))\n",
    "try:\n",
    "    from Code.Utils.Alias import *\n",
    "    METHOD_ALIASES=1\n",
    "except:\n",
    "    print(\"The module pyMez.Code.Utils.Alias was not found\")\n",
    "    METHOD_ALIASES=0\n",
    "    pass\n",
    "    ```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## An example\n",
    "```python\n",
    "#-----------------------------------------------------------------------------\n",
    "# Name:        alias.py\n",
    "# Purpose:     Function that provides exec string to define common aliases for \n",
    "#              for functions\n",
    "# Author:      Aric Sanders\n",
    "# Created:     2/21/2016\n",
    "# License:     MIT License\n",
    "#-----------------------------------------------------------------------------\n",
    "\"\"\" Module that defines functions for handling alias definitions in Classes \"\"\"\n",
    "\n",
    "#-------------------------------------------------------------------------------\n",
    "# Standard imports\n",
    "\n",
    "import re\n",
    "import types\n",
    "\n",
    "#-------------------------------------------------------------------------------\n",
    "# Module Functions\n",
    "\n",
    "def alias(object):\n",
    "    \"\"\" Creates aliases that map all non built-in methods to  \n",
    "    both lowerCapitalCase and all_lower_with_underscore naming conventions the\n",
    "    output is a list of strings to be used with exec(list[i]) \"\"\"\n",
    "    \n",
    "    old_names=[]\n",
    "    split_name=[]\n",
    "    exec_list=[]\n",
    "    new_name=''\n",
    "    \n",
    "    # Get all the atributes without __ in the begining\n",
    "    for attribute in dir(object):\n",
    "        if not re.match('_',attribute):\n",
    "            try:\n",
    "                if type(eval('object.%s'%attribute)) is types.MethodType:\n",
    "                    old_names.append(attribute)\n",
    "            except:pass\n",
    "    # If they are camelCase make them all lower with underscores or vice versa\n",
    "    for name in old_names:\n",
    "        if re.search(r'[A-Z]+',name) and not re.search(r'_',name):\n",
    "            split_upper_case=re.split(r'[A-Z]+',name)\n",
    "            upper_matches=re.findall(r'[A-Z]+',name)\n",
    "            for index,piece in enumerate(split_upper_case):\n",
    "                if index<len(upper_matches):\n",
    "                    new_name=new_name+piece+'_'+upper_matches[index].lower()\n",
    "                else:\n",
    "                    new_name=new_name+piece\n",
    "            exec_list.append(('self.'+new_name+'='+'self.'+name))\n",
    "\n",
    "        elif re.search(r'_',name):\n",
    "            split_name=name.split('_')\n",
    "            for index,piece in enumerate(split_name):\n",
    "                if index==0:\n",
    "                    new_name=piece\n",
    "                else :\n",
    "                    new_name=new_name+piece.title()\n",
    "            exec_list.append(('self.'+new_name+'='+'self.'+name))\n",
    "        #else: pass\n",
    "    return exec_list\n",
    "\n",
    "#-------------------------------------------------------------------------------\n",
    "# Class Definitions\n",
    "\n",
    "class MyTestClass():\n",
    "    \"\"\" A class to test the alias function: call it in a for loop inside of \n",
    "    __init__() method \"\"\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.littleAttribue=[]\n",
    "        self.i_like_underscores=[]\n",
    "        # this calls and executes the alias function\n",
    "        for command in alias(self):\n",
    "            exec(command)\n",
    "\n",
    "    def myFunctionNumberOne(self):\n",
    "        pass\n",
    "    def my_function_number_two(self):\n",
    "        pass\n",
    "    def my_funtion_Number_three(self):\n",
    "        pass\n",
    "\n",
    "#-------------------------------------------------------------------------------\n",
    "# Module Scripts\n",
    "def test_alias():\n",
    "    print \" Before making the instance the attributes defined are:\"\n",
    "    for attribute in dir(MyTestClass):\n",
    "        print 'Attribute Name: %s'%(attribute)\n",
    "    new=MyTestClass()\n",
    " \n",
    "    print \" After making the instance the attributes defined are:\"\n",
    "    for attribute in dir(new):\n",
    "        print 'Attribute Name: %s'%(attribute)\n",
    "#-------------------------------------------------------------------------------\n",
    "# Module Runner\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    \n",
    "    test_alias()\n",
    "```\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
