In this article we will look at creating a simple hello world program using wxPython. This program will create and display simple window with a big button on it. Up on clicking the button program will exit. Use the following code to create hello world program. You must already have wxPython library installed
We will go line by line here and try to explain what’s going on in this program. Most of the lines of self explanatory. If you are just getting started in programming the following explanation will be helpful.
Import wxpython library
Inherit from wx.Frame class. This is useful style for most of the programs that you will build. You can create one base frame or window and put rest of GUI widgets on top of it like Text controls, buttons,images, tables etc.
Instantiate the inherited frame the desired title. parent argument is usually None for main windows.
Create a button with label “Kill Me”. The first argument is parent. In this case we use “self” which is the main window we have just created.
Bind the button click event (EVT_BUTTON) of the killButton to kill method. Whenever, EVT_BUTTON event is fired aka the killButton is clicked, kill method will be called.
This line will cause the window to get displayed on screen. It’s customary to call this method after being done with construction of GUI i.e. create main window, place widgets, bind event like we did here.
Create wxPython application by call wx.App. Every wxPython program must have this application.
Start the main loop. Which will hand over control to wxPython library. This post explains why main loop has to be called.
Output
This program will launch the following window. The button takes all the available space on the window since there are no other widgets. You need a few more lines of code to make the button look like what users are used to – small and horizontal. You can exit the program by clicking the button.
In this post we will go over the topic of easy way to install wxpython. The following command will install wxpython easily in python3.
pip install wxpython
Python 2
Older versions of wxpython can be installed by downloading binaries (for windows) from sourceforge . The binaries are available for both Windows and MacOS.
Linux
The pip install command should work on linux also. However, if you are stuck on old linux vesions. You can try installing wxpython using your distro’s package manager like apt-get or yum. You can search for exact version and package name available on your platform using the following commands for debian variants.
apt-cache search wxpython
┌──(kali㉿kali)-[~] └─$ apt-cache search wxpython gnumed-client - medical practice management - Client psychopy - environment for creating psychology stimuli in Python pyscanfcs - scientific tool for perpendicular line scanning FCS python3-genx - differential evolution algorithm for fitting python3-opengl - Python bindings to OpenGL (Python 3) python3-pyface - traits-capable windowing framework python3-squaremap - wxPython control to display hierarchic data as nested squares python3-wxgtk-media4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.media) python3-wxgtk-webview4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.html2) python3-wxgtk4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit soundgrain - Graphical interface to control granular sound synthesis modules wxglade - GUI designer written in Python with wxPython wxpython-tools - Tools from the wxPython distribution
Successful installation
Use the following command to check if the installation is successful or not.
PS C:\Users\godson> python
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'4.1.1 msw (phoenix) wxWidgets 3.1.5'
>>>
As shown above it should print current version of wxpython installed if the installation is successful.
Contacts are We are going to use built in Contacts.framework to import all contacts in our app. To display a list of contacts, you must have access to the user’s address book. Apple does a great job of protecting the user’s privacy, so you can’t read any of their contacts’ data without asking the user for permission. Similar restrictions apply to access the user’s camera, location, photos, and more.
Whenever we need access to privacy-sensitive information, you are required to specify this in your app’s Info.plist file. This file keeps track of many of your app’s properties, such as its display name, supported interface orientations, and, in the case of accessing a user’s contacts, Info.plist also contains information about why you need access to the user’s contacts.
Let’s go step by step:-
Add usage description in Info.plist file for contacts.
Open Plist file and click on plus button to add new row for contact usage description.
Add “Privacy – Contacts Usage Description“ in key
Select Type as String
Write the usage purpose of contacts in your app.
Import Contacts Framework in your class.
import Contacts
Request for Contact permission
func getAuthStatus() -> CNAuthorizationStatus{
return CNContactStore.authorizationStatus(for: .contacts)
}
func requestForAccess(_ completionHandler: @escaping (_ accessGrandted: Bool, _ authStatus: CNAuthorizationStatus) -> Void) {
let authorizationStatus = getAuthStatus()
switch authorizationStatus {
case .authorized:
completionHandler(true, CNAuthorizationStatus.authorized)
break
case .notDetermined:
let store = CNContactStore()
store.requestAccess(for: .contacts, completionHandler: { (authorized: Bool, error: Error?) in
if authorized {
completionHandler(true, CNAuthorizationStatus.authorized)
}
else {
if self.getAuthStatus() == CNAuthorizationStatus.denied {
completionHandler(false, CNAuthorizationStatus.denied)
}
}
} )
break
case .denied :
completionHandler(false, CNAuthorizationStatus.denied)
break
default:
completionHandler(false, CNAuthorizationStatus.notDetermined)
break
}
}
Above two function will check Contact authorisation status. If not determined it will show alert for contact permission. Keep in mind you can ask Contact permission only once. Once user denied you can just open Setting screen for enable Contact permission.
Fetch Contact Using CNContactStore:-
do {
let store = CNContactStore()
var results = [CNContact]()
let containers = try store.containers(matching: nil)
for container in containers {
let predicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
let keyToFetch = [CNContactIdentifierKey,
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactEmailAddressesKey,
CNContactPhoneNumbersKey,
CNContactPostalAddressesKey,
CNContactNoteKey,
CNContactOrganizationNameKey] as [Any]
let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keyToFetch as! [CNKeyDescriptor])
results.append(contentsOf: contacts)
}
return results
}
catch
{
// print("Error1 is \(error)")
}
We create a CNContactStore instance and this object is used to communicate directly with the Contacts system on iOS. In this method, we wrap our code in a do-catch statement because two of the methods we use are throwing methods.We can retrieve different values using different Keys like first name, last name, contact image, mobile number, address, emails etc. We then create an array that contains a number of constant keys. These keys directly relate to the information your app has access too.
There is different container Group in Native phonebook. We can retrieve Contacts from different Container according our need. Here we are retrieving contacts of all Groups using store.containers(matching: nil) and iterate it one by one to fetch contacts.
store.unifiedContacts will return array of CNContact which you can store in Your app data or in your app’s database and display contacts In your own tableview Format.
The reason it was added is primarily for privacy reasons — the notes field can contain any information you might have on the contact; and a lot of times this information is significantly more sensitive than just the contact information.
To facilitate PCI compliant credit card collections Fusebill provides a AJAX Transparent Redirect endpoint which you can use to securely capture customer’s credit cards. If you are adding the first payment method on a customer, it will be set to the default payment method automatically.
This API action is authenticated with a separate Public API Key. If you do not have that key, please contact Fusebill Support. The Public Key can only be used to authenticate the Transparent Redirect action.
Google reCAPTCHA required.
Fusebill leverages reCAPTCHA technology to ensure payment method data captured is provided by a human and to protect against bots and scripting.
Using Fusebill’s public site key, the client is presented with a captcha widget.
The user then verifies that they are human, starting with a check box. The user may be presented with additional verification steps such as an image recognition task.
The captcha widget then verifies with Google that the user is human, and returns a response token.
That response token is then sent to Fusebill with the payment method data for our system to validate and verify.
Fusebill Environment
reCAPTCHA Public Site Key
Staging (stg-payments.subscriptionplatform.com)
6LcI_GwUAAAAAJZu0VvB68DdxNxb5ZcBIwAX7RVj
Sandbox and Production (payments.subscriptionplatform.com)
This is the Fusebill customer ID of the customer you wish to add the card to
Yes
Number
PublicAPIKey
This is your public API key.
This is found in fusebill account under Settings > Integrations > Transparent Redirect.
Yes
String
CardNumber
This is the credit card number.
Yes
Number
FirstName
The first name of the cardholder.
Yes
String
LastName
The last name of the card holder.
Yes
String
ExpirationMonth
Expiration month on the credit card.
Yes
Number
ExpirationYear
Expiration on the credit card.
Yes
Number
CVV
The credit card verification number.
Yes
Number
recaptcha
Recaptcha token response.
Yes
String
riskToken
WePay Risk token
No+
String
clientIp
Client/Customer IP address
No+
String
email
Customer Email address
No+
String
address1
First line of payment method address.
No*
String
address2
Second line of payment method address.
No*
String
city
City of the payment method
No*
String
stateId
State ID of the Payment method.
These can be found by performing a GET to v1/countries
No*
Number
countryId
Country ID of the payment method.
These can be found by performing a GET to v1/countries
No*
Number
postalZip
PostalZip of the payment method
No*
String
paymentCollectOptions
Object that allows specifying an amount to collect when creating the card.
Only works through Json {
"collectionAmount": 1.0
}
No
Object
+ Denotes a field required for Fusebill Payments API Risk Fields * Denotes fields required for AVS and may be required by your account’s Gateway. These fields are also required if using Fusebill Payments accounts as AVS is mandatory.
Notes:- Address information can optionally be captured as well.
Sample Code
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AJAX Transparent Redirect</title>
http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
var verifyCallback = function(response) {
document.getElementById("mySubmit").disabled = false;
$('input#recaptcha_token').val(response);
};
var expCallback = function () {
document.getElementById("mySubmit").disabled = true;
grecaptcha.reset();
};
var onloadCallback = function() {
grecaptcha.render('exampleWithCallback', {
'sitekey': '',
'callback': verifyCallback,
'expired-callback': expCallback
});
};
function AJAXTransparentRedirect() {
var dataString = 'CustomerId='+ $('input#CustomerId').val() +
'&PublicApiKey=' + $('input#PublicApiKey').val() +
'&SuccessUri='+$('input#SuccessUri').val() +
'&FailUri='+$('input#FailUri').val() +
'&CardNumber='+$('input#CardNumber').val() +
'&FirstName='+$('input#FirstName').val() +
'&LastName='+$('input#LastName').val() +
'&ExpirationMonth='+$('input#ExpirationMonth').val() +
'&ExpirationYear='+$('input#ExpirationYear').val() +
'&makeDefault='+$('input#MakeDefault').val() +
'&Cvv='+$('input#Cvv').val() +
'&recaptcha=' + $('input#recaptcha_token').val();
alert(dataString);
//Set up the request
var request = $.ajax({
type: "POST",
url: "https://stg-payments.subscriptionplatform.com/api/paymentsv2/",
data: dataString
});
//Set up the callback functions
request.done(function (msg) {
//$('#response').append("
Encrypted alphanumeric string to authenticate your Zoho credentials.
scope*
String
Specify the value as crmapi
id*
String
Specify unique ID of the “record” or “note” to which the file has to be attached.
content
FileInputStream
Pass the File Input Stream of the file
attachmentUrl
String
Attach a URL to a record.
* – Mandatory parameter
Important Note:
The total file size should not exceed 20 MB.
Your program can request only up to 60 uploadFile calls per min. If API User requests more than 60 calls, system will block the API access for 5 min.
If the size exceeds 20 MB, you will receive the following error message: “File size should not exceed 20 MB“. This limit does not apply to URLs attached via attachmentUrl.
The attached file will be available under the Attachments section in the Record Details Page.
Files can be attached to records in all modules except Reports, Dashboards and Forecasts.
In the case of the parameter attachmentUrl, content is not required as the attachment is from a URL.
Example for attachmentUrl: crm/private/xml/Leads/uploadFile?authtoken=*****&scope=crmapi&id=<entity_id>&attachmentUrl=<insert_ URL>
Python Code to Upload a file to a record
Here’s a simple script that you can use to upload a file in zoho using python.
In the program, you need to specify values for the following:
Your Auth Token
The ID of the Record
The uploadFile Request URL in the format mentioned above
The File Path i.e the location of the File
import MultipartPostHandler, urllib2
ID ='put the accounts zoho id here '
authtoken = 'your zoho authtoken here'
fileName = "your file name here - i use the full path and filename"
opener = urllib2.build_opener(MultipartPostHandler.MultipartPostHandler)
params = {'authtoken':authtoken,'scope':'crmapi','newFormat':'1','id':ID, 'content':open(fileName,"rb")}
final_URL = "https://crm.zoho.com/crm/private/json/Accounts/uploadFile"
rslts = opener.open(final_URL, params)
print rslts.read()
Recently I was faced with an issue where a long running process is listening on loop back IP (127.0.0.1) on port 8080 on one of our servers and client programs on other machines are trying to access it on server’s local IP 10.91.20.66. We ended up at this situation when we have updated server configuration and restarted the server program and forgot to change IP binding info in config file from loop back to local IP. Server got busy with it’s work, with lots of customer’s connections already, by the time we have discovered that some services of server are not accessible to client programs on other machines. So, the dummy’s guide to fixing it by changing config and restarting the server program is not an option as we can’t risk to disconnect existing customers. So, hot patching is the only option until we can restart the program at next scheduled down time.
I could have fixed this in couple of ways either by adding few lines to iptables configuration or by writing simple socket program in python. The task is to forward data coming in on local IP port 8080 to loop back IP (127.0.0.1) port 8080 and send replies back to source address. Forwarding one socket data to other socket is pretty trivial using Python’s socket library and Twisted made it even more trivial, so I went with the following solution using Twisted.
That’s it. Now, all I needed to do is to run this program by the following command
twistd -y portforwarder.py
This simple program is made possible by the heavy lifting done by twisted library. Interested folks can look under hood at twisted’s portforward.py module.
Celery is a distributed task queue that allows us to execute jobs in background. This article explains how to set up Celery with Django to perform a background task.
Advantages:
Large or small, Celery makes scheduling such periodic tasks easy.
You never want end users to have to wait unnecessarily for pages to load or actions to complete. If a long process is part of your application’s workflow, you can use Celery to execute that process in the background, as resources become available, so that your application can continue to respond to client requests.
Celery uses brokers to pass messages between a Django Project and the Celery workers. We will use Redis as the message broker.
Installation
Before diving into Celery, follow the below setup points
Create a new virtualenv ‘venv’ using following command:
$ virtualenv venv
To activate the environment use command:
$ source ./venv/bin/activate
Install django and create a django project ‘myproject’. Make sure to activate a virtualenv, create a requirements.txt file and run the migrations. Then fire up the server and navigate to http://localhost:8000/ in your browser. You should see the familiar “Congratulations on your first Django-powered page” text. When done, kill the sever.
Now we will integrate Celery into our Django project with the following steps:
Step 1:
Inside the myproject directory i.e beside your settings.py create a new file called celery.py and add the following code in that:
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
Let’s break down what happens in the first module, first we import absolute imports from the future, so that our celery.py module will not clash with the library:
from __future__ import absolute_import
Then we set the default DJANGO_SETTINGS_MODULE for the celery command-line program:
Specifying the settings here means the celery command line program will know where your Django project is. This statement must always appear before the app instance is created, which is what we do next:
app = Celery('myproject')
This is your instance of the library, you can have many instances but there’s probably no reason for that when using Django.
We also add the Django settings module as a configuration source for Celery. This means that you don’t have to use multiple configuration files, and instead configure Celery directly from the Django settings.
You can pass the object directly here, but using a string is better since then the worker doesn’t have to serialize the object when using Windows or execv:
app.config_from_object('django.conf:settings')
Next, a common practice for reusable apps is to define all tasks in a separate tasks.py module, and Celery does have a way to autodiscover these modules:
To ensure that the Celery app is loaded when Django starts, add the following code into the __init__.py file that sits next to your settings.py file:
from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
Test that the Celery worker is ready to receive tasks:
$ celery -A myproject worker -l info
Kill the process with CTRL-C. Now, test that the Celery task scheduler is ready for action:
$ celery -A myproject beat -l info
That’s it! You can now use Celery with Django. For more information on setting up Celery with Django, please check out the official Celery documentation.
The PayPal REST APIs are supported in two environments. Use the Sandbox environment for testing purposes, then move to the live environment for production processing.
The following endpoints address are two environments:
Sandbox (for testing) : https://api.sandbox.paypal.com
Live (production) : https://api.paypal.com
A complete REST operation is formed by combining an HTTP method with the full URI to the resource you’re addressing. For example, here is the operation to create a new payment:
POST https://api.paypal.com/v1/payments/payment
The PayPal REST sdk can be obtained through pip
pip install paypalrestsdk
OAuth Request / Response
import paypalrestsdk
api = paypalrestsdk.set_config(
mode="sandbox", # sandbox or live
client_id="CLIENT_ID",
client_secret="CLIENT_SECRET")
api.get_access_token()
Client Id and Secret Id can be obtained from the application created in the paypal account.
For the following each API call, you’ll need to set request headers, including the access token.
Creating a WebProfile:
web_profile = WebProfile({
"name": Web_Profile_Name,
"presentation": {
"brand_name": "BusinessName",
"logo_image": URL to logo image,
"locale_code": "US"
},
"input_fields": {
"allow_note": 1,
"no_shipping": 1,
"address_override": 1
},
"flow_config": {
"landing_page_type": "Login"
}
})
web_profile.create(): # Will return True or False
name:
The name of the web experience profile which should be unique among the profiles for a given merchant.
presentation:
It contains the parameters for style and presentation.
input_fields:
Parameters for input fields customization:
allow_note : It enables the buyer to enter a note to the merchant on the paypal page during checkout.
no_shipping : Determines whether or not PayPal displays shipping address fields on the experience pages.
0 – PayPal displays the shipping address on the PayPal pages.
1 – PayPal does not display shipping address fields whatsoever.
2 – If you do not pass the shipping address, PayPal obtains it from the buyer’s account profile.
address_override : Determines if the PayPal pages should display the shipping address supplied in this call, rather than the shipping address on file with PayPal for this buyer.
0 – PayPal pages should display the address on file
1 – PayPal pages should display the addresses supplied in this call instead of the address from the buyer’s PayPal account.
flow_config:
Parameters for flow configuration
landing_page_type : Type of PayPal page to be displayed when a user lands on the PayPal site for checkout.
Billing – The Non-PayPal account landing page is used
Have you ever wished to blink browser tab on certain activity to get user’s attention?
Here is a scenario: Suppose there is a chat application installed on your website. Now what if the user of your website has multiple tabs opened in his browser and there is an incoming message in your website? How will you make your user realize that there is an unread message? Of course you can play some music, but it has some limitations. For instance, user may be listening to some songs or speakers could be muted. If none of them is applicable then also he has to go through each and every single tab in his browser and find out the one which is playing that music.
Visual blinking is the best way to get user’s attention and the easiest way to achieve that is to keep blinking the title of your website until user returns.
Here’s a JavaScript function to do so:
var blinkTab = function(message) {
var oldTitle = document.title, /* save original title */
timeoutId,
blink = function() { document.title = document.title == message ? ' ' : message; }, /* function to BLINK browser tab */
clear = function() { /* function to set title back to original */
clearInterval(timeoutId);
document.title = oldTitle;
window.onmousemove = null;
timeoutId = null;
};
if (!timeoutId) {
timeoutId = setInterval(blink, 1000);
window.onmousemove = clear; /* stop changing title on moving the mouse */
}
};
Just execute the function like below and browser tab will start blinking: