Happy Thanksgiving 2015

Happy Thanksgiving, Everybody!

May the Lord bless us all with a Spirit of Gratitude and the resulting Joy that comes from it.

Love and peace,

Joe

Advertisements

Download an App from Google Play to a PC & Install it on a Tablet (Sideload)

Download an App from Google Play to a PC & Install it on a Tablet

Download App to PC

ref How to Download Android Apps from Play Store to PC?

  1. Find the App URL on google play store for your account
  2. Here’s the App URL for Cogi – Notes & Voice Recorder
    https://play.google.com/store/apps/details?id=com.cogi.mobile
  3. Copy the id == com.cogi.mobile
    From the App URL
    To https://apps.evozi.com/apk-downloader/
  4. Click on newly appeared button
    “Generate Download Link”
Result:
  Package Name: com.cogi.mobile [Play Store]
  File Size: 12.1 MB
  QR Code: View
  MD5 File Hash: ee75eba0fef749dba8796c2eb5cab309
  Last Fetched: 2015-08-03 21:31:36
  Version: 1.17.2 (94)
  1. Click on the newly appeared button
    “Click here to download =com.cogi.mobile now”
  2. Put the download into yourPC PATH_TO_Apps/Cogi/
  3. Verify the md5 hash
>cd yourPC PATH_TO_Apps/Cogi/
>rem use whatever md 5 checker you have
>md5chk.py com.cogi.mobile.apk ee75eba0fef749dba8796c2eb5cab309
      file length: 12736720
    file checksum: ee75eba0fef749dba8796c2eb5cab309
expected checksum: ee75eba0fef749dba8796c2eb5cab309
True

Install the Downloaded APK on the Tablet

refs:

  1. Connect USB cable from tablet to pc
  2. Copy [drag & drop] com.cogi.mobile.apk
    From: yourPC PATH_TO_Apps/Cogi/
    Into: yourPC PATH_TO_Tablet/Tablet/Download
    N.B.: Navigate to yourPC PATH_TO_Tablet/Tablet/Download in your PC File Browser
    when your Tablet is USB connected.
  3. Disconnect USB cable from tablet to pc
  4. On Tablet Go to Menu > Settings > [General] > Security > and check “Unknown Sources”
    4.1 the cnet link ALSO says
    Menu > Settings > [General] > Security > and check “Verify Apps”
    “Depending on your device, you can also choose to be warned before installing harmful apps. This can be enabled by selecting the Verify apps option in the Security settings.” N.B. For me this was ALREADY CHECKED
  5. On Tablet go to My Files > Download
    N.B. “Downloaded Apps” is a Category NOT A FOLDER
  6. Tap com.cogi.mobile.apk
    [I notice that this app gets A TON of permissions – should have checked earlier]
  7. Tap Install
    RESULTS:
    – Cogi appears in “Downloaded Apps” Category
    – Cogi appears in the Apps Tab of the Top Screen
  8. IMPORTANT Go back to Menu > Settings > [General] > Security > and UNCHECK “Unknown Sources”

THE END

Analyze Python cProfile stats created with pstats.dump_stats() off line.

Background

In order to improve Code Performance, I need to find functions that are good candidates for Cython implementation.

Here’s the link to the Python Docs for Code Profiling. Pay attention to cProfile.

I asked and answered this on stack overflow here.

Preamble

Previously I have essentially done the following:

import cProfile, pstats, StringIO
pr = cProfile.Profile()
pr.enable()
# ... my code did something ...
pr.disable()
s = StringIO.StringIO()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)

ps.dump_stats('stats.dmp')  # dump the stats to a file named stats.dmp

So now I have the file named ‘stats.dmp’ stored off line.

Here’s how I used pstats to analyze the ‘stats.dmp’ file for human consumption off line.

The Code

#!/usr/local/bin/python2.7
# -*- coding: UTF-8 -*-
"""analyze_dmp.py takes the file INFILEPATH [a pstats dump file] Producing OUTFILEPATH [a human readable python profile]
Usage:   analyze_dmp.py INFILEPATH  OUTFILEPATH
Example: analyze_dmp.py stats.dmp   stats.log
"""
import sys, os
import cProfile, pstats, StringIO

def analyze_dmp(myinfilepath='stats.dmp', myoutfilepath='stats.log'):
    out_stream = open(myoutfilepath, 'w')
    ps = pstats.Stats(myinfilepath, stream=out_stream)
    sortby = 'cumulative'

    ps.strip_dirs().sort_stats(sortby).print_stats(.3)  # plink around with this to get the results you need

NUM_ARGS = 2
def main():
    args = sys.argv[1:]
    if len(args) != NUM_ARGS or "-h" in args or "--help" in args:
        print __doc__
        s = raw_input('hit return to quit')
        sys.exit(2)
    analyze_dmp(myinfilepath=args[0], myoutfilepath=args[1])

if __name__ == '__main__':
    main()

I tested this with a .dmp file created on Linux & analyzed on Windows XP. It worked FINE. The above Python file is named, “analyze_dmp.py”.

An Additional Resource

I also found out how to use the Python command line to analyze stats.dmp in an interactive way here.

Here’s the command line i used on Windows XP.

ipython -m pstats stats.dmp

lxml.html basic parse methods for [url, file, string]

lxml.html examples of parsing from

  • URLs
  • Files
  • Strings

URLs

import lxml.html
htmltree = lxml.html.parse('http://joecodeswell.com')

htmltree.xpath("//title")[0].text

'''
OUTPUT:
'JoeCodeswell.com'
'''

Files

N.B. Save ‘http://joecodeswell.com’ as a file named ‘JoeCodeswell.com.htm’.
Make sure to cd to the dir containing the file before running the following.

import lxml.html
htmltree = lxml.html.parse('JoeCodeswell.com.htm')

htmltree.xpath("//title")[0].text

'''
OUTPUT:
'JoeCodeswell.com'
'''

Strings

N.B. Save ‘http://joecodeswell.com’ as a file named ‘JoeCodeswell.com.htm’.
Make sure to cd to the dir containing the file before running the following.

import lxml.html

f = open('JoeCodeswell.com.htm', 'r'); the_string = f.read(); f.close()
htmltree = lxml.html.fromstring(the_string)

htmltree.xpath("//title")[0].text

'''
OUTPUT:
'JoeCodeswell.com'
'''

Easy to Understand web2py Grid Custom Search

web2py Grid Custom Search WITHOUT specifying a custom search_widget

The custom_search.html view contains the EASIER TO UNDERSTAND customization code. Here is the technique.

  1. Make the SQLFORM.grid’s Standard Search Input hidden.
  2. Define Custom Search Input elements with onchange events that send their values to the to the hidden Standard Search Input.
  3. Insert the Custom Search Input elements after the Standard Search Input (“#w2p_keywords”) using jQuery .insertAfter().
    • This prevents them from showing up on Edit or View pages.
    • Insert them in reverse order of them appearing on the page.

You can find an older version of this on web2pyslices.com

Here is the Controller code. Note the absence of a custom search_widget argument in the grid function call.

# in default.py Controller
def custom_search():
    '''
    Implements SQLFORM.grid custom search 
        WITHOUT specifying a custom search_widget,
            and so needing to read & understand the clever web2py implementation source code.
    The custom_search.html view contains the EASIER TO UNDERSTAND customization code.
    The technique:
        1. Make the grid's Standard Search Input hidden.
        2. Define Custom Search Input elements 
            with onchange events that 
                send their values to the to the hidden Standard Search Input.
    '''
    query=((db.contact.id > 0))
    fields = (db.contact.id, 
        db.contact.l_name, 
        db.contact.f_name, 
        db.contact.prime_phone,
        db.contact.date_modified,
        )

    headers = {'contact.id':   'ID',
           'contact.l_name': 'Last Name',
           'contact.f_name': 'First Name',
           'contact.prime_phone': 'Primary Phone',
           'contact.date_modified': 'Info Last Updated',
           }    
    init_sort_order=[db.contact.l_name]   

    grid = SQLFORM.grid(query=query, 
        fields=fields, 
        headers=headers, 
        orderby=init_sort_order,
        searchable=True,  
        user_signature=False, 
        create=True, deletable=False, editable=True, maxtextlength=100, paginate=25)

    return dict(grid=grid)    

Here is the View code.

<!-- In custom_search.html view -->
{{extend 'layout.html'}}
{{block head}}
{{super}}
<script>

function phoneSrch(){
    var srch ='contact.prime_phone contains '+'"'+jQuery('#joephone').val()+'"';
    $("#w2p_keywords").val(srch);
}
function lnameSrch(){
    var srch ='contact.l_name starts with '+'"'+jQuery('#joelname').val()+'"';
    $("#w2p_keywords").val(srch);
}

$(document).ready(function(){
  // Make the Grid Standard Search Input hidden  
  $("#w2p_keywords").prop("type", "hidden");   

  // Insert the Custom Search Input elements after 
  //     the Standard Search Input ("#w2p_keywords")
  //     using jQuery .insertAfter().
  //     This prevents them from showing up on Edit or View pages.
  //     Insert them in reverse order of them appearing on the page.
  var input2Str  = '<div class="joeinputclass" style="padding-bottom:10px;" >';
  input2Str += '<span class="joelabelclass" >Primary Phone contains: ';
  input2Str += '</span><input name="joephone" id="joephone" type="text" ';
  input2Str += 'onchange="phoneSrch()" style="width:150px;" ><br/></div>';
  $(input2Str).insertAfter("#w2p_keywords");
  var input1Str  = '<div class="joeinputclass" style="padding-bottom:10px;">';
  input1Str += '<span class="joelabelclass" style="padding-right:18px;" >';
  input1Str += 'Last Name starts with: </span><input name="joelname" ';
  input1Str += 'id="joelname" type="text"  onchange="lnameSrch()" ';
  input1Str += 'style="width:150px;" ></div>';
  $(input1Str).insertAfter("#w2p_keywords");
});

</script>
{{end}}
<h2>Contacts</h2>
<div id="theweb2pygrid">
{{=grid}}
</div>

Good contact Table

##Contact Table Def
Here’s a good contact table def i want to remember.
– Automatic change for Info Last Updated datetime field.
– Uses represent

db.define_table("contact",
    Field("f_name", "string",  requires=IS_NOT_EMPTY() ),
    Field("l_name", "string", requires=IS_NOT_EMPTY() ),
    Field("m_initial", "string", default=None),
    Field('prime_phone', requires=IS_NOT_EMPTY(), comment='phone eg: (650) 555-1212'),
    Field('other_phone',   comment='phone eg: (650) 555-1212'),
    Field('email', requires=IS_EMPTY_OR(IS_EMAIL()) ),    
    #Field('ca_address', 'reference ca_address', writable=False, readable=False),
    Field("address_line1", "string", requires=IS_NOT_EMPTY() ),
    Field("address_line2", "string"),
    Field("city", "string", requires=IS_NOT_EMPTY() ),
    Field("state", "string", length=2, default='CA', writable=False),
    Field("zip", "string", length=5, default=None),
    Field("date_modified", "datetime", default=datetime.datetime.now(),
        update=request.now,   # working - needed below line
        writable=False, readable=True,
    # http://strftime.org/   AND http://stackoverflow.com/questions/9678172/modify-column-output-for-sqlform-grid-in-web2py
        represent=lambda x, row: x.strftime("%c"),
        comment='Last change date of contact info.'),

      ) 

Debug web2py Actions with iPython

My Notes re debugging web2py Actions with iPython

My system

  • Using web2py 2.9.5-stable+timestamp.2014.03.16.02.35.39 (Running on Rocket 1.2.6, Python 2.7.5)
  • On Windows XP in C:\web2py

iPython log

Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.

IPython 0.13.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: cd C:\web2py
C:\web2py

In [2]: from gluon import shell

In [3]: shell.run('fish/default/view_or_add_client_trips/?client_id=2', plain=True, import_models=True)
{'grid': <gluon.html.DIV object at 0x0289C930>}

In [4]: