Saturday, November 21, 2015

Quick Langauge Reference: Python

interactive prompt, for quickly testing code

    run (with no args):

        python


    # this starts an interactive shell  
    print "hi"

    use:
        ctrl-c to stop execution
        ctrl-d to exit


introspection/reflection

    # will print out object methods in the shell
    dir()

    #example

    import struct
    dir()
    dir(struct)  


line comment

    #

mulitline comment

    """
    you can use pydoc style quotes,
    though it's kinda a hack
    """

continue long lines

    this is a long line \
    that will be continued

combine two lines

    print "hi" ; print "there"


tab/spaces:

    best practice is (apparently) to use spaces instead of tabs

Note: This seems counter intuitive to me. No one seems to agree on how many spaces to use.   PEP 8 recommends 4 spaces, and Google recommends 2 spaces.  Personally, I think it makes more sense to use \t and let everyone set their own tabstop.


print

    print "hello world"


    concatinate string

    # with space
    a = "hello",  "world"
    print a
    # hello world


    # without space
    print "hello" + "world"
    helloworld


    WARNING: python3 has apparently changed this basic function syntax.  :-)
    You'll need to use parens with python3: print(string)


variables, no declaration needed

    # simple
    a = 1

    # can assign a list to a list
    a,b,c = 1,2,3

    #can chain
    a = b = c = 1


python assumes all function variables are local.  to access the global scope use

    global varname


basic strings

    s = 'A string constant'
    s = "another constant"



There is no difference between ' and " (unlike in Perl and PHP).  Typically is seems like python code I see tends to prefer ' (easier to type?)

multi line strings use a triple-quote syntax:

    s = """
    This is
    your string
    """


analogue of php require_once (include)


    EXAMPLE

        #### (file: config.py)
        # can be nested data structure

        constant1 = "value1"
        constant2 = "value2"


        ####  (consumer.py)
        # note, no .py extension.

        import config

        # note, by default, everything is under the namespace:
        print config.constant1
        print config.constant2


    better - wrap with try/except

        # create file named modulename.py
        # then in second script run  
        try:
            import modulename
        except ImportError:
            print 'importing modulename failed'



command line args

    import sys

    # 1 is first arg
    a = sys.argv[1]



function

    def concat(a, b):
        return a + b;


    functions can be called with named arguments

        concat('1', '2')

    or

        concat( a = '1', b = '2' )


    functions can also set default values

    def example( a, b = 0 ):
        return a + b;



nested functions

    you can define function in a function and return it:


    def example():
        def ret():
            print "hi"
        return ret

    t = example()
    t()
    #hi


more on strings

    a = 'string'
    a = "string"
    a = """string"""
    a = '''string'''

    # unicode
    a = u'strng'

    # binary
    a = b'strng'

    # regular expression
    regex = r"(\w)"


string formatting

    WARN: python3 changes this syntax:

    a = 5
    b = "hello"

    buf = "A = %d\n , B = %s\n" % (a, b)
    print buf

    # prints:
    # A = 5
    #  , B = hello

    c = 10
    buf = "C = %d\n" % c
    print buf
    C = 10



    You could as well use format:

    >>> print "This is the {}th tome of {}".format(5, "knowledge")
    This is the 5th tome of knowledge


    note: % will be deprecated in python 3.1


# string manipulation

    # to lower  case
    a.lower()

    # replace
    a.replace( find, start, [num_of_times] )

    # starts with string
    a.startswith( "/" )

    # ends with string
    a.startswith( "/" )


# regular expressions

    import re

    # substitute
    re.sub(r"(\w)(\w+)(\w)", yourreplacement, yourstr)

    # match
    if re.search('http', yourstr) != None:

int

    b = 2

float

    b = 2.0

booleans

    True, False

null value

    None


conditional

    if a < b:
        do_something();
    elif a < c:
        do_something_else()
    else:
        default_case()


logical operators (these do what you'd expect)

    and
    or
    not

    # don't forget and type &&  ||  !  :-)


main hook

    if __name__ == "__main__":
        main()


exit program:


    import sys
    sys.exit(2)


    #another example
    if sys.argv[1] == '':
        print "usage is ./yourprogram.py site url "
        sys.exit(2)



array

    empty list
    a = []

    with values
    a = ['spam', 'eggs', 100, 1234]

    # length

    len(a)

    #note: multidimensional arrays work as you'd expect

    # whitespace between elements is ignored:
    # valid syntax:
    a = [1,
            2,
            3,
            4
                ]


test if value is in array

    has_spam = 'spam' in s


loops

    for n in [1,2,3]:
        print n


list/array methods:

    list.append(item)
    list.extend(List)
    list.insert(i, item)
    list.remove(item)
    list.pop(i)
    list.index(item)
    list.count(item)
    list.sort()  # in place
    list.reverse()


hash/dictionary


    stock = {
        "key": "value",
        "key2": 2
    }

    stock['key3'] = 2

    # remove item

    del stock['key3']


nested data structure

    # nest arrays and
    a = [ {'a': 1}, {'a': 2} ]

    print(a[1]['a'])
    #prints: 2

loop over dictionary/hash

    d = {'x': 1, 'y': 2, 'z': 3}
    # loop over keys, read into var 'key'
    for key in d:
        print key, 'corresponds to', d[key]

    # loop over key and value
    for key, value in d.iteritems():
        print key, 'corresponds to', value


    breaking out of a loop:

        break        exists loop
        continue    skips iteration


cast

    int()
    float()
    str()
    chr()
    unichr()
    ord()
    hex()
    oct()

tuple (invariant data, like a constant struct)

    coord = (2,3)


set (like a dictionary with no data)

    a = { 'a', 'b' }

while loop

    while link != '':
        # do something

files

    f = open('doo.txt')
    while line = f.readLine()
        print line
    f.close()

user input

    name = raw_input("enter your name:")

array slice

    select all items j <= k < j
    a[i:j]

    -1 counts starting from end of list

    replace list subset with another

    a[1:2] = [1,2,3,4]

    concatenate lists
    a = a + b


tuples

    pack data together as a single unit
    a = ('GOOG', 100, 635.2)

    access like array

set

    like array keys, no duplicates

    s = set([3,4,5])


    operations
    |    union
    &    intersection
    -    difference (subtract)
    ^    nand


place holder

    if you need to stick something in a code block for syntax check
    does nothing but fill space

        if 1:
            pass

test if string contains substring

    x = 'hello'
    y = 'll'
    y in x
    # True

index of string

    >>> print "hello".find('h')
    0
    >>> print "hello".find('ss')
    -1


exceptions

    try:
        do_somthing()

    except:
        print "error: your error "



    full syntax
    except NameError, IndexError as msg:
        print "error", msg      


    raising execptions (throw)

        raise ValueError('invalid number')

    print error # older syntax

        try:
            doX()
        catch Exception, e:
            print e

generator

    use instead of return
        yield

    the function maintains persistent state and pauses at the yeild line

    to grok: it's a static function with static global variables.


 
lamba

    for short anon function, no (), no return statement, one line
 
        square = lambda x: x ** 2

        print square(2)
 


Object Oriented Programming in Python

For me, OOP in Python is difficult to use compared to Java/C#.  To me it just feels like OOP was bolted onto Python as an after-thought.  Or probably more accurately, it copied from a language which bolted OOP on as an after-thought.  OOP was not present in the pre 1.0 releases of Python.

Overall, I really wish Python had (a) explicit variable declarations like `var x` and (b) implicit self.  The scoping rules also feel screwy (why do we need `global`?  If can see a variable in a parent scope, why can't Python?)

Otherwise, you might initially think if you write a set of functions that access global variables, all you need to do to convert them into a class, is to indent them all and add a class name to the top.  For example, this syntax would make sense to me:


    # i'm a function accessing a global variable
    a = 1
    def get_a():
        return a

    # now i'm a class
    class your_class:
        a = 1 # now an instance variable
        def get_a():
            return a

This is simple and makes sense to me.  Unfortunately it won't work at all. :-)  Python forces you to rewrite every single function signature and variable reference.

After struggling with Python's approach, IMO the easiest way to understand understand OOP in Python is to realize that: Python is NOT really an OOP language, any more than Perl is.  It's a multi-paradigm language which happens to provide a little OOP "syntax sugar."  But it's really bitter tasting sugar. :-)


As a result, the OOP "object.function" syntax is largely redundant.  It's passing an object reference around as the first argument, and has a very lightweight syntax manipulation that just converts this syntax:

 
    obj.f(a)  ->  f(obj, a)

IOW, it's just moving the "obj" to inside the function.  That's not OOP; that's just a regular expression.


Anyway, accepting the screwy OOP syntax, here's an object example:

    class Test:

        # instance variable  
        your_variable = ''

        # static variable
        your_static = ''

        # constructor
        def __init__(self, a):
            # no class scope of variables.  must use explicit self.
            self.your_variable = a  
            Test.your_static = a  

        # like perl class
        def your_method( self, a ):
            self.your_variable = a  
            # ...


initialize class

    # NOTE: no 'new' keyword
    # this is less painful

    t = Test()


extending another class

    class Test( BaseClass ):

        #...

execute shell command

    import subprocess

    p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    for line in p.stdout.readlines():
        print line,
    retval = p.wait()



    older method (prints output)

        os.system(cmd_string)



modules:

    save as yourfile.py


        import yourfile

    call as:

        yourfile.function()


    import indivdual functions into script namespace


        from yourfile import *
        from yourfile import f1, f2


urllib vs urllib2


    generally you should use the newest lib 2
    urlib (old) has the encode function

     urllib.urlencode({'abc':'d f', 'def': '-!2'})
    'abc=d+f&def=-%212'


    in python 3, everything has been merged into urllib



easy install for modules

    # shell level installer

    wget http://peak.telecommunity.com/dist/ez_setup.py
    python ez_setup.py


    # cache downloade files with
    easy_install  -b  /path/to/build/dir/

    # install from cache
    easy_install  /path/to/build/dir/


install pip to install new modules. like PCAN for Pearl


    new versions of python (>3.4) already include pip

    for old versions download

        https://bootstrap.pypa.io/get-pip.py

    run

        python    get-pip.py

    add python Scripts/ to PATH, if it's not already


    #verbose output
    pip -vvv install flask


better parsing of command line args

    # allow a hook for cli
    if __name__ == "__main__":
        opt = OptionParser()
        opt.add_option("-d", "--database", help="EZCONNECT string", action="store",
                     type="string", dest="db")
        opt.add_option("-n", "--requests", help="number of requests", action="store",
                     type="int", dest="requests", default=10)
        opt.add_option("-c", "--concurrency", help="number of concurrent connections",
                     action="store", type="int", dest="concurrency", default=1)
        opt.add_option("-s", "--sql", help="SQL query or PL/SQL block",
                     action="store", type="string", dest="sql")
        opt.add_option("-b", "--bind", help="dictionary of bind parameters",
                     action="store", type="string", dest="bind")
        (options, args) = opt.parse_args()
        bench = Orabench(options)
        bench.run()


python debugger

    within a python file:

        import pdb
        ...
        pdb.set_trace() begin the debugger at this line when the file is run normally

    start debug mode

        python -m pdb  <name>.py  [args]    begin the debugger
        help [command] view a list of commands, or view help for a specific command

    control execution

        l(ist)       list 11 lines surrounding the current line
        w(here)      display the file and line number of the current line
        n(ext)       execute the current line
        s(tep)       step into functions called at the current line
        r(eturn)     execute until the current functionṡs return is encountered
        b[#]         create a breakpoint at line [#]
        b            list breakpoints and their indices
        c(ontinue)   execute until a breakpoint is encountered
        clear[#]     clear breakpoint of index [#]
        q(uit)       exit the debugger

    changing variables / interacting with code

        p <name>      print value of the variable <name>
        ! <expr>      execute the expression <expr>



operators

    Operator    Description    Example

    +    Addition - Adds values on either side of the operator     a + b will give 30
    -    Subtraction - Subtracts right hand operand from left hand operand     a - b will give -10
    *    Multiplication - Multiplies values on either side of the operator     a * b will give 200
    /    Division - Divides left hand operand by right hand operand     b / a will give 2
    %    Modulus - Divides left hand operand by right hand operand and returns remainder     b % a will give 0
    **    Exponent - Performs exponential (power) calculation on operators     a**b will give 10 to the power 20
    //    Floor Division - The division of operands where the result is the quotient in which the digits after the decimal point are removed.     9//2 is equal to 4 and 9.0//2.0 is equal to 4.0



    ==     Checks if the value of two operands are equal or not, if yes then condition becomes true.     (a == b) is not true.
    !=     Checks if the value of two operands are equal or not, if values are not equal then condition becomes true.     (a != b) is true.
    <>     Checks if the value of two operands are equal or not, if values are not equal then condition becomes true.     (a <> b) is true. This is similar to != operator.
    >     Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true.     (a > b) is not true.
    <     Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true.     (a < b) is true.
    >=     Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true.     (a >= b) is not true.
    <=     Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true.     (a <= b) is true.


    =    Simple assignment operator, Assigns values from right side operands to left side operand     c = a + b will assigne value of a + b into c
    +=    Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand     c += a is equivalent to c = c + a
    -=    Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand     c -= a is equivalent to c = c - a
    *=    Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand     c *= a is equivalent to c = c * a
    /=    Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand     c /= a is equivalent to c = c / a
    %=    Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand     c %= a is equivalent to c = c % a
    **=    Exponent AND assignment operator, Performs exponential (power) calculation on operators and assign value to the left operand     c **= a is equivalent to c = c ** a
    //=    Floor Dividion and assigns a value, Performs floor division on operators and assign value to the left operand     c //= a is equivalent to c = c // a


    &     Binary AND Operator copies a bit to the result if it exists in both operands.     (a & b) will give 12 which is 0000 1100
    |     Binary OR Operator copies a bit if it exists in eather operand.     (a | b) will give 61 which is 0011 1101
    ^     Binary XOR Operator copies the bit if it is set in one operand but not both.     (a ^ b) will give 49 which is 0011 0001
    ~     Binary Ones Complement Operator is unary and has the efect of 'flipping' bits.     (~a ) will give -61 which is 1100 0011 in 2's complement form due to a signed binary number.
    <<     Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.     a << 2 will give 240 which is 1111 0000
    >>     Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand.     a >> 2 will give 15 which is 0000 1111


    and     Called Logical AND operator. If both the operands are true then then condition becomes true.     (a and b) is true.
    or    Called Logical OR Operator. If any of the two operands are non zero then then condition becomes true.     (a or b) is true.
    not    Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false.     not(a and b) is false.



    in    Evaluates to true if it finds a variable in the specified sequence and false otherwise.     x in y, here in results in a 1 if x is a member of sequence y.
    not in    Evaluates to true if it does not finds a variable in the specified sequence and false otherwise.    x not in y, here not in results in a 1 if x is not a member of sequence y.


    is    Evaluates to true if the variables on either side of the operator point to the same object and false otherwise.     x is y, here is results in 1 if id(x) equals id(y).
    is not    Evaluates to false if the variables on either side of the operator point to the same object and true otherwise.     x is not y, here is not results in 1 if id(x) is not equal to id(y).



Python Operators Precedence. The following lists all operators from highest precedence to lowest.


    Operator    Description
    **    Exponentiation (raise to the power)
    ~ + -    Ccomplement, unary plus and minus (method names for the last two are +@ and -@)
    * / % //    Multiply, divide, modulo and floor division
    + -    Addition and subtraction
    >> <<    Right and left bitwise shift
    &    Bitwise 'AND'
    ^ |    Bitwise exclusive `OR' and regular `OR'
    <= < > >=    Comparison operators
    <> == !=    Equality operators
    = %= /= //= -= += *= **=    Assignment operators
    is is not    Identity operators
    in not in    Membership operators
    not or and    Logical operators

Quick Language Reference: PHP

GETTING STARTED

A good graphical ide is Netbeans with the php pack.  Or install cygwin and the php interpreter

php can be run from the command line:

        file: yourscript.php

        <?php
            echo "hello world";
        ?>

Then to execute run (assuming php exe is in PATH)

        php  yourscript.php

To syntax check a script  you can run (like lint):

    php -l   yourscript.php


Notes: The start tag is required.  The closing tag of a php block at the end of a file is optional, and in some cases omitting it is helpful when using include() or require() so unwanted whitespace will not occur at the end of files, and you will still be able to add headers to the response later. It is also handy if you use output buffering, and would not like to see added unwanted whitespace at the end of the parts generated by the included files.

Otherwise, everything outside of the tags are interpreted as string literal

        <?php ?> tags cannot be nested inside another <?php ?> tag
        and ;  at end of commands is required


Print out server config

        <?php echo phpinfo(); ?>

Print contents of data structure or object

        <?php var_dump($somevar); ?>

The log file is defined in php.ini (global php config file)

        log_errors = On
        error_log = C:\temp\php_error.log


To run as a shell script, add to top of file

    #!/usr/bin/env php

TESTING COMPATIBILITY

 # test code in multiple php versions
 http://3v4l.org/UCALa


PRINTING

To print a string to STDOUT, use:

    echo "hello world";
    print "hello world";


COMMENTS

    # single line comment (Perl style)
    // single line comment (Javascript style)
    /* multi line comments */


LOGICAL OPERATORS

    Example Name    Result
    $a and $b       And     TRUE if both $a and $b are TRUE.
    $a or $b        Or      TRUE if either $a or $b is TRUE.
    $a xor $b       Xor     TRUE if either $a or $b is TRUE, but not both.
    ! $a            Not     TRUE if $a is not TRUE.
    $a && $b        And     TRUE if both $a and $b are TRUE.
    $a || $b        Or      TRUE if either $a or $b is TRUE.


COMPARISON OPERATORS

    Example         Name            Result
    $a == $b        Equal           TRUE if $a is equal to $b after type
                                     juggling.  EG: '' == 0 == false
    $a === $b       Identical       TRUE if $a is equal to $b, and they are of
                                     the same type. (introduced in php 4)
    $a != $b        Not equal       TRUE if $a is not equal to $b after type
                                     juggling.
    $a <> $b        Not equal       TRUE if $a is not equal to $b after type
                                     juggling.
    $a !== $b       Not identical   TRUE if $a is not equal to $b, or they are
                                     not of the same type. (introduced in php 4)
    $a < $b         Less than 
    $a > $b         Greater than
    $a <= $b        Less than or equal to
    $a >= $b        Greater than or equal to


ARITHMETIC OPERATORS

    +       Addition
    -       Subtraction
    *       Multiplication
    /       Division
    %       Modulus (division remainder)
    ++      Increment
    --      Decrement

    NOTE: there is no exponent ** or ^ operator.  Use: pow( base, exponent )


ASSIGNMENT OPERATORS

    Operator Example Is The Same As
    =        x=y     x=y
    +=       x+=y    x=x+y
    -=       x-=y    x=x-y
    *=       x*=y    x=x*y
    /=       x/=y    x=x/y
    .=       x.=y    x=x.y
    %=       x%=y    x=x%y


ERROR CONTROL OPERATOR

    @           can be prepended to value functions to suppress error

    For example:

        $text = @file_get_contents('non_existent_file');
        $value = @$cache[$key];

 Warning: use this carefully.  You want to see most errors.

 A more acceptable (safer) use is for arrays:

  # manually check for null values if needed
  $value = @$yourarray['non-existent-key'];
  do_some_magic($value);
 

VARIABLES

Notes: There's no equivalent of "use strict" as in perl.  Though you can turn on warnings for use of null variables with the error_reporting E_STRICT flag

declaration and assignment

    $a = "asdf";
    $b = 2;


    $c = NULL;

variables are NULL if:
        it has been assigned the constant NULL.
        it has not been set to any value yet.
        it has been unset().

check NULL value with:
        is_null()
        or $c === NULL
        or $c !== NULL


PARSE COMMAND LINE ARGS

for example:

    script.php plain-arg --foo --bar=baz 'plain arg 2' -abc

These will be stored in array $argv

$argv[0] is always the name that was used to run the script.


    function parseArgs($argv){
      array_shift($argv);
      $o = array();
      foreach ($argv as $a){
        if (substr($a,0,2) == '--'){
          $eq = strpos($a,'=');
          if ($eq !== false){
            $o[substr($a,2,$eq-2)] = substr($a,$eq+1); }
          else {
            $k = substr($a,2);
            if (!isset($o[$k])){ $o[$k] = true; }
          }
        } else if (substr($a,0,1) == '-'){
          if (substr($a,2,1) == '='){
            $o[substr($a,1,1)] = substr($a,3);
          } else { foreach (str_split(substr($a,1)) as $k){
            if (!isset($o[$k])){ $o[$k] = true; } }
          }
        }
        else { $o[] = $a; }
      }
      return $o;
    }

use

    $args = parseArgs($_SERVER['argv']);


LOOP OVER STARDARD INPUT

 <?php
 $f = fopen( 'php://stdin', 'r' );

 while( ( $line = fgets( $f ) ) !== false ) {
   echo $line;
 }

 fclose( $f );


DEFINE CONSTANTS

    define('DS', DIRECTORY_SEPARATOR);
    echo DS;


STRINGS

like with perl, double quoted strings interpolate variables

    $a = "hello";
    print "$a world";
    # Outputs: hello world

Use single quotes for better performance, if possible.
Single quotes are literals, variables are not interpreted.

    <?php
    echo 'this is a simple string';

    echo 'You can also have embedded newlines in
    strings this way as it is
    okay to do';

    echo 'Arnold once said: "I\'ll be back"';
    // Outputs: Arnold once said: "I'll be back"

    echo 'You deleted C:\\*.*?';
    // Outputs: You deleted C:\*.*?

    echo 'You deleted C:\*.*?';
    // Outputs: You deleted C:\*.*?

    echo 'This will not expand: \n a newline';
    // Outputs: This will not expand: \n a newline

    echo 'Variables do not $expand $either';
    // Outputs: Variables do not $expand $either
    ?>


A string is also an array of characters
NOTE: if you get the first char of a string instead of a string,
code is executing $string[0]... an array assumed where there is none

 $s = "hello there";
 echo $s[3];  # prints l


PHP heredoc syntax (do not indent closing marker)

    $str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;


NOTE: It is no problem for a string to become very large. php imposes no boundary on the size of a string; the only limit is the available memory of the computer on which php is running.


REPLACE STRINGS

    str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

    It's worth skimming over all string manipulation functions:

        http://php.net/manual/en/ref.strings.php


INCLUDE FILE

Code must be loaded into global memory space before it can be called. The following calls will scan the currect folder by default if no path information is given.

        try to include, ignore if missing or not found
        <?php include "somefile.php"; ?>

        try to include, die if file missing
        <?php require "somefile.php"; ?>

        like include, ignore if already included
        <?php include_once "somefile.php"; ?>

        like require, die if file missing, only include once
        <?php require_once "somefile.php"; ?>


For absolute paths, it is sometimes helpful to define constants like:

      // which page are we on?  eg /some/path/to/script.php
      if( ! defined( 'WEB_PATH' ) ) define('WEB_PATH', $_SERVER['PHP_SELF']);
 
      // web root dir. eg /some/path/to
      //if( ! defined( 'WEB_ROOT' ) ) define('WEB_ROOT', dirname(WEB_PATH));
      if( ! defined( 'WEB_ROOT' ) ) {
              $path = dirname(WEB_PATH);
              // avoid "//" at root
              if ( $path == '/' ) $path = '';
              define('WEB_ROOT', $path);
      }
 
 
      // what is the file name only?  // eg script.php
      if( ! defined( 'WEB_FILE' ) ) define('WEB_FILE', basename(WEB_PATH));
 
      // physical file path (system).  eg: /var/www/html/yoursite
      if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(dirname(__FILE__)));

      if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(__FILE__));


NAME VS ID

On an html form element like <input id="" name="" />

  ID is used mostly for javascript
  NAME is used for form submission

If the name has [], like:

  example[]

then php will parse it as an array of repeating elements.


WARNING: php also performs automatic replacement of special chars in names. For example

      name="a.b"  becomes  "a_b"  in $_POST

For safest results, stick with these chars for input names:

     alpha number _ [ ] 


ARRAYS

Arrays and hashes are the same thing.  One uses ints, the other strings.

WARNING: some functions will expect sequential indexes (for example fputcsv).  php does not automatically 'fill in' missing indexes.

define an array with:

        $arr = array();

assign values with:

        $arr[] = 134;
        $arr[] = 234;
   
    or

        $arr = array( 123, 234 );


define hash with:

  <?php
  $arr = array("foo" => "bar", 12 => true);

  echo $arr["foo"]; // bar
  echo $arr[12];    // 1
  ?>


hash/arrays can be nested any way you want :-)


multidimensional array

  <?php
  $arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));

  echo $arr["somearray"][6];    // 5
  echo $arr["somearray"][13];   // 9
  echo $arr["somearray"]["a"];  // 42
  ?>

print array

    print_r($array);

serialize dump as valid php code

   var_export( $array );

iterating with index

  $array = array(1, 2);
  $count = count($array);
  for ($i = 0; $i < $count; $i++) {
   echo "\nChecking $i: \n";
   echo "Bad: " . $array['$i'] . "\n";
   echo "Good: " . $array[$i] . "\n";
   echo "Bad: {$array['$i']}\n";
   echo "Good: {$array[$i]}\n";
  }

array iteration with foreach

  foreach ($array as $value) {
  }

hash iteration

  foreach ($array as $key => $value) {
   unset($array[$key]);
  }

alternate iteration (older syntax)

  while ($el = current($arr)) {
   $carr[ $el[$x] ] = $el[$y];
   next($arr);
  }


NOTE: In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.  Referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).

  <?php
  $arr = array(1, 2, 3, 4);
  foreach ($arr as &$value) {
    $value = $value * 2;
  }

  # $arr is now array(2, 4, 6, 8)
  unset($value); // break the reference with the last element, may do inside loop
  ?>

array functions:

    pop and returns the last value of the array,
    shortening the array by one element.
    array_pop ( $array )

shift an element off the beginning of array

    array_shift( $array )
 
add to end


    int array_push ( $array , $var [, $var2... ] )
    or,
    $your_array[] = "new item";

hash specific

    array_values, array_keys

    more:
    http://www.php.net/manual/en/ref.array.php


ARRAY OPERATORS

    Example    Name         Result
    $a + $b    Union        Union of $a and $b.
    $a == $b   Equality     TRUE if $a and $b have the same key/value pairs.
    $a === $b  Identity     TRUE if $a and $b have the same key/value pairs
        in the same order and of the same types.
    $a != $b   Inequality   TRUE if $a is not equal to $b.
    $a <> $b   Inequality   TRUE if $a is not equal to $b.
    $a !== $b  Non-identity TRUE if $a is not identical to $b.


FUNCTIONS

    define functions

    <?php
  # typical function
        function a($n){
          b($n);
          return ($n * $n);
        }

     variable pass by reference, use &
        function b(&$n){
          $n++;
        }

        echo a(5); //Outputs 36

  # WARNING, only variables can be passed by reference!
  # array( 1,2,3 ) cannot be passed by ref, it must be assigned to var
    ?>


NOTE: to access a global variable inside a function, you must re-declare it as global:


 $a = 1;
 function example() {
  print $a;   // $a not defined
  global $a;  // now $a points to variable $a in the global scope
  print $a;   // $a is 1
 }

 multiple variables can be declared with , operator:

     global $a, $b, $c ;


NOTE: php does not support function overloading, nor is it possible to undefine or redefine previously-declared functions.

However php does allow:

  default values to be set to primitives

  # variable arguments, default set in def
  function example($a, $b=0) {
   //$b is optional

  }

  also the type of the arg can be tested
  function do_somthing( $data ) {

   if ( is_array( $data ) ) {
    // do something
   } else {
    // do something else
   }
  }


nested functions:

All functions are declared in the global scope, unless defined in a class (then it's class-scoped)

  <?php
  function foo()
  {
    function bar()
    {
   echo "I don't exist until foo() is called.\n";
    }
  }

  /* We can't call bar() yet
     since it doesn't exist. */

  foo();

  /* Now we can call bar(),
     foo()'s processesing has
     made it accessible. */

  bar();

  ?>


Both variable number of arguments and default arguments are supported in functions. See also the function references for func_num_args(), func_get_arg(), and func_get_args() for more information.


anonymous functions

Only recent versions of php support the concept of closures.

  <?php
  $greet = function($name)
  {
   printf("Hello %s\r\n", $name);
  };

  $greet('World');
  $greet('php');
  ?>


NOTE: Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header. Inheriting variables from the parent scope is not the same as using global variables

            $callback = function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };


return by reference

  function &bar()
  {
   $a = 5;
   return $a;
  }

get a reference to a defined function

  <?php
  echo "test";
  function test1() {
    echo " works";
  }

  $test2 = 'test1'; # just use string name
  $test2();
  ?>

test if function exists

  if(function_exists('testfn') ) {}


GET/POST DATA

    <?php
      if( $_GET["name"] || $_GET["age"] )
      {
         echo "Welcome ". $_GET['name']. "<br />";
         echo "You are ". $_GET['age']. " years old.";
         exit();
      }
    ?>
    <html>
    <body>
      <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
      Name: <input type="text" name="name" />
      Age: <input type="text" name="age" />
      <input type="submit" />
      </form>
    </body>
    </html>


    hashes defined:
    $_GET
    $_POST

    $_REQUEST  contains both GET and POST values
    $_SERVER   contains server/environment data


     WARNING:  PHP mangles names with ., replaces with _


COOKIES

set cookie
    setcookie(name, value, expire, path, domain);

    <?php
    setcookie("user", "Alex Porter", time()+3600);
    ?>

read cookie

    <html>
    <body>
    <?php
    if (isset($_COOKIE["user"]))
      echo "Welcome " . $_COOKIE["user"] . "!<br />";
    else
      echo "Welcome guest!<br />";
    ?>
    </body>
    </html>



SESSIONS

    start a session
    <?php
        session_start();
    ?>

    store session variable
    <?php
        session_start();
        $_SESSION['views'] = 1; // store session data
        echo "Pageviews = ". $_SESSION['views']; //retrieve data
    ?>

    test session var if set
    <?php
        if(isset($_SESSION['views'])) {
            $_SESSION['views'] = $_SESSION['views']+ 1;
        } else {
            $_SESSION['views'] = 1;
        }
    ?>

    destroy session var
    <?php
        unset($_SESSION['cart']);
    ?>

    destroy session
    <?php
        session_destroy();
    ?>


MYSQL DATABASE

core functions:

 mysqli mysqli_connect ([ string $host = ini_get("mysqli.default_host") [,
  string $username = ini_get("mysqli.default_user") [,
  string $passwd = ini_get("mysqli.default_pw") [,
  string $dbname = "" [,
  int $port = ini_get("mysqli.default_port") [,
  string $socket = ini_get("mysqli.default_socket") ]]]]]] )

 int mysqli_connect_errno ( void )
 string mysqli_connect_error ( void )

 bool mysqli_select_db ( mysqli $link , string $dbname )

 bool mysqli_ping ( mysqli $link )

 string mysqli_real_escape_string ( mysqli $link , string $escapestr )

 mixed mysqli_query ( mysqli $link , string $query [,
  int $resultmode = MYSQLI_STORE_RESULT ] )
 string mysqli_error ( mysqli $link )

 mixed mysqli_fetch_array ( mysqli_result $result [, int $resulttype = MYSQLI_BOTH ])
  MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH.

for assoc array only:

 mysqli_fetch_assoc


 mixed mysqli_insert_id ( mysqli $link )

 bool mysqli_close ( mysqli $link )


example:

        <?php
        include "lib/global.php";

        $mysqli = new mysqli($dbhost, $dbuser, $dbpass, $db);
        print "ok";

        if(!mysqli->connect_errno) {
            $sql = "SELECT * from tblPrize where SerialNumber > ? limit 5";
            if($stmt = $mysqli->prepare($sql)) {

                // type string, bind by ref to variable
                // 'typestrings', $var1, $var2, $var3
                // i = int , s = string, d = double, b = blob
                // bool mysqli_stmt::bind_param( string $types , mixed &$var1 [, mixed &$... ] )

                $stmt->bind_stmt_param("i", $serial);
                $serial = 1;
                $stmt->execute();

                $stmt->bind_result($serial, $prize);
                while ($stmt->fetch()) {
                    echo "$serial, $prize\n";
                }

                $mysqli->close();
            } else {
                echo 'Unable to connect';
                exit();
            }
        }

        ?>


ESCAPING HTML

     htmlentities( $s, ENT_QUOTES, 'UTF-8');

This takes an optional third argument charset which defines character set used in conversion. Presently, the ISO-8859-1 character set is used as the default.

    http://php.net/manual/en/function.htmlentities.php

An alternate function (less recommended) is

     htmlspecialchars()


ENCODE/DECODE URL DATA

 urlencode( $s )
 urldecode( $s )

 Be careful about variables that may match html entities. Things like &amp, &copy &pound &curren are parsed by the browser and the actual entity is used instead of the desired variable name. This is an obvious hassle that the W3C has been telling people about for years. The reference is here: á¹  http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2.


TRY/CATCH

    try {
        echo inverse(5) . "\n";
        echo inverse(0) . "\n";
    } catch (Exception $ex) {
        echo 'Caught exception: ' . $ex->getMessage() . "\n";
    }

throwing: message [, code]

    throw new Exception('2 is not allowed as a parameter', 6);


READ/WRITE FILES

read small file into a string

    $file = file_get_contents ('YourFile.txt');

loop over lines

    $handle = fopen($YourFile, 'r');
    while (($buffer = fgets($handle, 4096)) !== false) {
        echo $buffer;
        echo "\n";
    }
    fclose($handle);


WRITE TO FILE

    $myFile = "testFile.txt";
    $fh = fopen($myFile, 'w') or die("can't open file");
    $stringData = "Floppy Jalopy\n";
    fwrite($fh, $stringData);
    $stringData = "Pointy Pinto\n";
    fwrite($fh, $stringData);
    fclose($fh);


READ WEBPAGE

    #Open a site as file
    $read = fopen("http://www.yoursite.com", "r")
                or die("Couldn't open file");
    /# read the bytes with fread ...

    # alt, for small files:
    # read whole file
    echo file_get_contents("http://127.0.0.1/");

    # write to file
    file_put_contents ( 'newfile.txt', $your_string );



OBJECT ORIENTED PHP, OOP

Note  'var' keyword is  for declaring class member variables in php4, and is no longer needed. It will work in php5, but will raise an E_STRICT warning in php5 up to version 5.3, as of which it has been deprecated. Though I happen to like it.  :-)


value objects (like struct in c, POJO in Java)

  class Person {
    var $id, $first_name, $last_name, $email;
  }


populate value object from a hash:

  # constructor
  public function __construct( $hash = null ) {
    if ( $hash ) {
   foreach ( $hash as $key => $value ) {
     # note: reference to variable $key
     $this->$key = $value;
   }
    }
  }


class example

    class PersonDAO {
       var $conn;

       function PersonDAO(&$conn) {
         $this->conn =& $conn;
       }

       function save(&$vo) {
         if ($v->id == 0) {
           $this->insert($vo);
         } else {
           $this->update($vo);
         }
       }


       function get($id) {
         #execute select statement
         #create new vo and call getFromResult
         #return vo
       }

       function delete(&$vo) {
         #execute delete statement
         #set id on vo to 0
       }

       #-- private functions

       function getFromResult(&vo, $result) {
         #fill vo from the database result set
       }

       function update(&$vo) {
          #execute update statement here
       }

       function insert(&$vo) {
         #generate id (from Oracle sequence or automatically)
         #insert record into db
         #set id on vo
       }
    }



 # access functions and variables in the class with:

  $this->your_variable_name;
  $this->your_function_name();


public/private/static keywords


 // static member variable
 private static $verbose = 1;

 // static function
        public static function something($data) {
  //
 }

 ...


 Then you can call externally with:

  TheClass::something($data);

 or call variable with

  if ( TheClass::$verbose ) {
   //...
  }



INCREASE MEMORY

edit php.ini

 max_execution_time=1800
 max_input_time=1800
 memory_limit=128M

or set in  .htaccess

 php_value max_execution_time 1800
 php_value max_input_time 1800
 php_value memory_limit 128M


to strip automatic slashes

 php_value magic_quotes_gpc off

turn off error reporting

 php_value display_errors off
 php_value output_buffering 8096


do not stop script if user disconnects

 int ignore_user_abort ([ string $value ] )



CHANGE HEADER

<?php
  # note: you can't manipulate headers after you write content to the browser
  header('Content-type: text/xml');
?>


SMTP WITH PEAR:


   <?php
   require_once "Mail.php";

   $host = "mail.emailsrvr.com";
   $username = "yourgmailuser@gmail.com";
   $password = "****************";

   $from = "test <name@domain.com>";
   $to = "Some Person <name@domain.com>";
   $subject = "Test email using php SMTP\r\n\r\n";
   $body = "This is a test email message";


   $headers = array ('From' => $from,
  'To' => $to,
  'Subject' => $subject);

   $smtp = Mail::factory('smtp',
     array ('host' => $host,
        'auth' => true,
        'username' => $username,
        'password' => $password));

   $mail = $smtp->send($to, $headers, $body);

   if (PEAR::isError($mail)) {
  echo("<p>" . $mail->getMessage() . "</p>");
   } else {
  echo("<p>Message successfully sent!</p>");
   }
   ?>


   # notes: to send BCC, append email both
  to header Bcc: $to
  and "to1,$to" string


REFLECTION

    print_r( $obj )                          -- prints structure of hash
    var_dump( $obj )                         -- structure of hash, with types
    print_r( get_class_methods( $obj ) )     -- gets list of object methods.
    print_r( get_class_vars( $obj ) )        -- gets list of public vars


SET DEFAULT TIMEZONE

 # store all data internally as GMT:

 #   local tz 1 \
 #   local tz 2  + <-> webservice.php <-> gmt tz
 #   local tz 2 /

 date_default_timezone_set('Zulu');



 // timestamp to convert (just an example)
 // can also use: DateTime( $date_string )
 $timestamp = 1240349566;

 // FROM GMT TO LOCAL
 // set this to the time zone provided by the user
 $tz = $_SESSION['tz'];
 // create the DateTimeZone object for later
 $dtzone = new DateTimeZone($tz);
 // create a DateTime object
 $dtime = new DateTime();
 // set it to the timestamp (php >= 5.3.0)
 $dtime->setTimestamp($timestamp);
 // convert this to the user's timezone using the DateTimeZone object
 $dtime->setTimeZone($dtzone);
 // print the time using your preferred format
 $time = $dtime->format('g:i A m/d/y');

 // FROM LOCAL TO GMT
 // time to convert (just an example)
 $time = 'Tuesday, April 21, 2009 2:32:46 PM';
 // set this to the time zone provided by the user
 $tz = $_SESSION['tz'];
 // create the DateTimeZone object for later
 $dtzone = new DateTimeZone($tz);
 // now create the DateTime object for this time and user time zone
 $dtime = new DateTime($time, $dtzone);
 // print the timestamp
 $timestamp = $dtime->format('U');


DATE MATH

 strtotime('last Sunday', strtotime('09/01/2010'));

 # snap to date starting on sun (week of date)
 if( ! defined( 'DATE_FORMAT' ) ) define ('DATE_FORMAT', 'Y-m-d H:i:s');
 date_default_timezone_set('Zulu');
 $tstart = strtotime($start) ;
 $weekday  = date('w',$tstart);
 if ( $weekday != 0 ) {
  $start = date(DATE_FORMAT, strtotime('last Sunday',$tstart));
 }
 # end snap


JSON

 $string = json_encode( $obj );
 $obj = json_decode( $string, 1 ); // 1 for hash

 $obj will be null on error, more info with:
 $intcode = json_last_error()


REDIRECT FUNCTION EXAMPLE:

This should be called before page is rendered, or buffer is flushed any chars echo'd to screen before this call can break redirect if output buffer is flushed

function redirect ( $url ) {
    header( 'Location: ' . $url ) ;
    exit();
}


SIMPLE PHP PAGE EXAMPLE WITH VIEWS/CONTROLLER

 $data     = $_REQUEST;
 $action   = $data['action'];
 $postback = $data['postback']; # set in hidden

 # validation
 if ( $postback ) {
  if ( ! @$data['dateStart'] && ! @$data['dateEnd'] ) {
   $data['message'] = 'Please select a date range';
   $postback = 0;
  } else if ( $action == 'report_referral' && ! @$data['reportType'] ) {
   $data['message'] = 'Please select a report type';
   $postback = 0;
  }
 }

 # controller
 switch( $action ) {

  case 'report_complete':

   echo view_report_search( $data );
   if ( $postback ) {
    # show search results on postback only
    echo view_report_complete( $data );
   }

   break;

  case 'report_billed':

   echo view_report_billed( $data );
   break;

  default:
   break;
 }


 # views

 # take data, render to html
 function view_report_complete( $data ) {
  $html = '';
  $html .= '<a href="?action=report_billed">test</a>';
  return $html;
 }

 function view_report_billed( $data ) {
  $html = '';
  $html .= '2';
  return $html;
 }



PHP GOTCHAS


There are a couple features in php that are counter intuitive (as compared to other languages).

1. The php interpreter ignores the read/write/execute permission bits on a file.  That means anything with a .php extension, or, .php. in the name is an executable file (since Apache allows multiple file extensions).  So for example, if someone uploads a file named fake_image.php.gif, it will be executable.  This also means: all files uploaded must be renamed, and assigned one extension.

Also, apache supports the idea of multiple file extensions.  Depending on how the server is set up, image.php.gif may execute as a php file, because the name contains ".php."  Meaning, any uploaded file should be renamed.

2. There is no good way to handle threading on all platforms.  At best it is only possible on linux with either:

 a. pcntl_fork  (on systems where lib is installed)
 b. lower level system call using & to force process into background

3. By default arrays are copied by value, not by reference.

Well, more exactly:  php does not copy arrays until you modify them - internally, they are always passed by reference, only if you modify them does it create an actual copy.

To pass by reference, you can use a function signature:

 function somefunction(&$argument){
   print_r($argument);
 }

So, if you change somefunction($o) to somefunction(&$o), you can see a small increase in array time.

However, this only works if the argument has been assigned to a variable.

php generally has issues with nesting operations.  In old versions of php you coulndn'even t do:

 somefunction( array(1,2,3) );

You had to do:

 $silly = array(1,2,3);
 somefunction( $silly );


Also for looping, if you expect to modify an array, you must use:

 foreach ( $things as &$thing ) {
  # now you have a reference to item in the array
 }
 unset ( $thing ); // break last ref

4. Variable scoping rules are not really what you might expect.  Most languages have the concept of a hierarchical scoping.  In php a function has no concept of a parent scope, they only exist in the global scope.

 $variable1 = 1;
 function a () {
  # i can't see $variable1

  $variable2 = 1;
  function nested_example () {
   # i can't see $variable2
   # it's not global either
  }

 }

All functions are registered under a global namespace.

The only communication to a function (outside of the arguments) is via global declaration or $this for objects

 $variable1 = 1;
 function b () {
  global $variable1
  # now i can see $variable1
 }

5. Functions can't be redefined, or undefined.  In javascript, the opposite is true.

6. Including files:

If a relative path is defined in an include, it's relative to the including script's path, not the included path's script.  This means that if you include the same file in two different scripts, the relative paths used in the included file may be wrong.

You can use  __FILE__ and dirname (__FILE__ ) to get the absolute location of an included script.

from docs:

If a path is defined whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.

dirname(__FILE__) gets the directory of the file being included while dirname($_SERVER['SCRIPT_FILENAME']) gets the directory of the file including it. The script simply finds the difference in how far off the base directory the two are and prints the appropriate number of '../' before the URL.

NOTE: dirname(__FILE__) can be replaced by __DIR__ in php greater than or equal to 5.3.0

or, keep all includes in the same directory.

7. There's no 'strict' variable definition.  the most you can have is warnings if a varible has been used without being defined.  That means it's harder to see if a variable is mistyped.  You can turn on E_STRICT and view error messages, though depending on the libararies you use, the log can fill up with so much text that it's hard to see the worthwhile messages.

8. You'd think there would be an 8, but there isn't.  That in itself is very counter-intuitive. :)

9. false == 0 == null;  To compare equality more strictly, you must use ===

10. order of operations on ternary a?b:x is counter intuitive, ? is left associative.  Always use parans around the entire thing, or avoid altogether.

 # won't work
 echo " ... " . $test?1:0 . " ... ";
 # prints: 1

 # ok
 echo " ... " . ($test?1:0) . " ... ";
  # prints: ... 0 ...

11. "magic quotes" aren't really magic, just a mistake in the language design.  Drop this in the .htaccess file to disable them:

 php_value magic_quotes_gpc off

otherwise, php will corrupt all your quote data by added backslashes to it.  You'll start to see strings like this show up:  "And that\\\'s not good" :)

12. php automatically mangles names of variable data in forms.  For example, if you have an HTML form with <input name="x.1"> this will show up as a variable "x_1" when the form is submitted.  Stick with alphanum and underscore to be safe.

13: Unlike most languages, php functions may return more than one type of data.

this becomes relevant, for example, as functions like strpos return:

 false (no match), and
 0 (beginnging of string)

 but:
  false == 0

If you are coming from a strictly typed langauge, it can be confusing that a function in php can return two different types of values: a boolean, or an int.  Every other language returns -1 as a 'false' value


14: Also there is no option of "overloading" the function by different types.  Just pass in the two different types, and check for them inside the function, manually. for example:

 function example( $a = null ) {

  if ( $a === null ) {
   // function was called without argument
  } else if ( is_array( $a) ) {
   // do somethign
  } else {
   // do somethign else
  }
 }

Though often it's clean to use the rule of thumb:

 a function can have one argument (an array/hash), and return one array/hash.

For example

 avoid:
  function avoidthis ( $a , $b , $c , $d , $e , $f );

 better:
  function avoidthis ( $data = array() );
  // where $data['a'], $data['b'] contain values of different types


PHP SECURITY CONSIDERATIONS

1. Don't trust user input.  Without some consideration, don't allow data the user submits to be used for:

 including files
  echoing contents of files
  data piped straight to command line util
 data piped straight to db
 dynamically executing php functions
 echoing directly to a web page

Ideally this data needs to be:

 A. scrubbed (restricted to a known set of characters)
 B. Restricted to known length.
 C. and escaped for the context it is used in.

Avoid using any information that is supplied by the user that is related to a filesystem, rather manage the filesystem yourself and map the user data to the file with a database.

Remember that a chunk of data is really two things:
 1. a peice of information
 2. a representation in a given context (html, sql, javascript, php, ...)

2. Be careful with functions like $response = file_get_contents($url);  Not only will it retrieve a URL, but it will retrieve any file on the system.

3. Always rename files that are uploaded (rename with file extension).  Maintain a "whitelist" of safe file types: *.txt, *.gif, *.jpg, etc.


Monday, November 9, 2015

"Fixing" the Python Interactive Shell Prompts

I like the concept of interactive shells for quickly testing new code.  The only issue I've had with the Python shell is the prompt (the >>> and ...) is a complete nuisance if you want to copy code out of the shell after testing it.  I can't even copy and paste something back into the same shell.  :-)

Also I think it would make more sense -- if there was any prompt at all -- that # should be added to the standard output and print statements.  That way, if the code was copied into a program, the testing output would just be ignored as comments.  (In some cases it could actually be useful as a comment, if it gives an example of data structure or function output)

So, I added a quick config file to "fix" the prompt noise.

Create a file such as ~/.pythonrc.py

And add this to the file:

import sys

# this is a patch so you can directly copy to/from the shell
# just remember to add a new line after a def as usual.

# clear those puppies!
sys.ps1 = ""
sys.ps2 = ""

# add a logger that prints output as a comment.
class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout
    def write(self, s):
        if s == '\n': # compress
            return
        lines = s.split("\n")
        for line in lines:
            if len(line) > 0:
                self.terminal.write("# "+line+"\n")
        #self.terminal.write("\n") # optional space
    def flush(self):
        pass

sys.stdout = Logger()


Then  run this before starting the `python` interactive shell (or drop it in your ~/.profile)
export PYTHONSTARTUP=~/.pythonrc.py  
When you start python shell, the prompts are gone. Then you will have an interactive terminal you can copy code directly from (and to itself):

Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information
def just_a_test(s):
        print s 
just_a_test('works')
# works

Sunday, November 1, 2015

Self Healing Technology is Here

The idea of self-healing technology seems futuristic, though I noticed it already exists in smartphones.

I gave my son my old Motorola Atrix 2 phone a couple years ago, and he uses it like a mini game platform.  (Interestingly, he uses the old smartphone much more than his Game Boy).  As a result, it's been dropped a couple hundred times, and even flown across the room a few times as well.  The thing appears to be nearly indestructable.

One day I noticed the screen had a lot of dead pixels after a bad fall.  I thought the phone was just about shot, but wondered if there was a way to fix them.  So I did a little research and learned, suprisingly, the dead pixels REPAIR THEMSELVES.  

I also read that freezing the phone helped speed up the process.  I was a bit skeptical, but wanted to try the experiment.  

I took out the battery, put the phone in a zip lock bag, and froze it over night.  The next day, I thawed it out in a towel (to avoid condensation).  After I turned it back on, the bad pixels were remarkably better.  What used to be a giant black streak on the phone was much less than half the size (smaller).  



Though I didn't take a photo of the screen initially for reference, so I couldn't tell exactly how much better it had improved.  So, I took a picture for reference, and repeated the freezing process.  The second time around, the bad spot was again about half the size.

After a week, I checked again -- lo and behold -- the phone was completely healed:


Apparently, if you just wait six months, the liquid crystals in the screen will fix themselves, but freezing seems to speed up the process.

Seems like freaky Skynet technology to me.   This is the first time I've ever seen a piece of technology heal itself. :-)

Simple Graphical Interface for FluidSynth


I had a Korg Triton synthesizer for a long time, and was thinking of getting a new synth for fun.  Though I noticed really everything for a synthesizer can be done in open source software now.  For example, you can download free .sf2 soundfont files (some of which sound more realistic than my Korg).  On Linux, you can use jack and fluidsynth to do the midi synthesis.  You can even do sequencing in Rosegarden, or standard multitrack recording in Ardour or Audacity.

The only physical piece of hardware you need is a usb midi device.  So for maybe under $100, you can get what would easily be a $1000 synth (if you were buying a traditional hardware synth).  :-)

The only downside, fluidsynth is by default a command line program.

There are some graphical front end programs for it, but I found them to be difficult to use for what I needed.  I typically use a synth for multitrack overdubs, or just playing around on, less for midi sequencing.  So, I wanted an interface that looked similar to a classic synth.  For example: I wanted to to see all the soundfont files as "voices" and then easily cycle through the instruments in each soundfont -- with one key press.   Or, to search through the soundfont files, for example, to see all "organ" voices at a glance.

So... I gave up on finding a simple graphical interface that worked for me, and I just spent a few days writing exactly what I wanted.  Also, it was a nice excuse to poke around Python.  I don't use it very often.   Also I thought it would be easier for others to take apart or extend.

The source code (single file) is at git hub:

    https://github.com/sevkeifert/fluidsynth-gui

The graphical interface looks like this:


The default tab:



The second tab (some level controls):




Features:

  • Put all your sound fonts in a folder, and select the folder.   Then, if you press the Up/Down arrows (on the sound font list) you'll quickly cycle through the voices.  If you press the Left/Right arrows, you'll quickly cycle through the available instruments contained in the soundfont. 
  • There's also a search filter at bottom.  (You can also search while the sountfont list has the focus, and this adds a search filter at bottom.)  For example, if you type "moog," the list will be filtered to only items that contain "moog" in the name.  When searching, SPACE is a wildcard.  ESC clears the search box.
  • If you organize the fonts in a folder, you can also search and navigate the folders from directly inside the Sound Font listing. 
  • You can load up to 16 sound fonts on your 16 midi channels.
  • On the second tab, you can set levels for gain/reverb/chorus.  
  • All control settings will be restored if you close and restart the app.

The interface is as simple as I could make it.  :-)

You'll need to setup fluidsynth first before using this gui.

In theory it should work on Windows, Mac and Linux (it just uses fluidsynth's socket interface).   I only have used it with xubuntu 14.04, FluidSynth version 1.1.6 so far.

Future/Planned Features ... ;-)

  • Add Checkbox that enables "More cowbell" 
  • Add new volume controls that go to "11" for extra "umph" when needed

--

On the other hand, if you only have one soundfont, you can use the existing GUI Qsynth instead.   In comparison, Qsynth looks like:


Though switching between soundfonts in Qsynth requires a few more steps.  You'll need to do this for every soundfont:

    Setup -> Soundfonts -> Open

Monday, August 24, 2015

Handy shortcuts for Vim

Here are a couple Bash shortcuts that have ended up being fairly useful for me.

Typically if I'm on a Linux command line, I'll need to open files by either the content of the file, or partitial file names.  For example,  I might want to quickly open  all the files that contain the string "Foo."   That, or I don't want to type a/very/long/path/to/some_file.txt.   I'll end up piping the output of `find` or `grep` into an editor repeatedly.  So I just made a couple short aliases that save on typing.    I'm not sure why I hadn't added these years ago :-)

The shortcuts look at everything under the current directory.

Of course, you can customize these to work with any editors or filetypes you are interested in... these are just examples.  

Drop these in your .bash_profile file:


# vim + grep = vig
# Open all files containing a particular string

# For example, to oen all files containing content "Foo", use
#     vig Foo
function vig(){ vim `grep -Ril --exclude='*.class' "$1"`; }


# vim + find = vif
# Open all files where the name contains a string.  
# For example, to open all files named "Foo...", use
#     vif  Foo
function vif(){ vim `find -iname "$1*"`; }


# vim + java = vij
# Open all files matching a class name
# For example, find all classes named Foo.java, use
#     vij Foo
function vij(){ vim `find -name "$1.java"`; }

Sunday, December 21, 2014

Create Postage Stamp Window Border Theme in XFCE

I noticed that XFCE window themes allow transparent (color: None), so I thought it would be funny to create a postage stamp window border.  This was tested on Xubuntu 14.04

# The theme is based on greybird.  Copy the theme to a new one called 'bumpy'

cd /usr/share/themes/

sudo cp -r Greybird bumpy

cd bumpy/xfwm4/


# then update the border files

sudo vi left-active.xpm


/* XPM */
static char * left_active_xpm[] = {
"8 24 3 1",
"  c None",
". c #cecece",
"x c #939393",
"x.......",
" x......",
"  x.....",
"   x....",
"   x....",
"  x.....",
" x......",
"x.......",
"x.......",
" x......",
"  x.....",
"   x....",
"   x....",
"  x.....",
" x......",
"x.......",
"x.......",
" x......",
"  x.....",
"   x....",
"   x....",
"  x.....",
" x......",
"x.......",
};

sudo vi bottom-active.xpm

/* XPM */
static char * left_active_xpm[] = {
"23 8 3 1",
"  c None",
". c #cecece",
"x c #939393",
"........................",
"........................",
"........................",
"........................",
"...xx......xx......xx...",
"..x  x....x  x....x  x..",
".x    x..x    x..x    x.",
"x      xx      xx      x",
};


sudo vi right-active.xpm


/* XPM */
static char * left_active_xpm[] = {
"8 24 3 1",
"  c None",
". c #cecece",
"x c #939393",
".......x",
"......x ",
".....x  ",
"....x   ",
"....x   ",
".....x  ",
"......x ",
".......x",
".......x",
"......x ",
".....x  ",
"....x   ",
"....x   ",
".....x  ",
"......x ",
".......x",
".......x",
"......x ",
".....x  ",
"....x   ",
"....x   ",
".....x  ",
"......x ",
".......x",
};


sudo vi bottom-left-active.xpm 


/* XPM */
static char * left_active_xpm[] = {
"16 16 3 1",
"  c None",
". c #cecece",
"x c #939393",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxx        ",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
};


sudo vi bottom-right-active.xpm

/* XPM */
static char * left_active_xpm[] = {
"16 16 3 1",
"  c None",
". c #cecece",
"x c #939393",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"        xxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
};


Now, your windows have postage stamp borders: