Feeds

Jacob Rockowitz: Webform module now supports importing submissions

Planet Drupal - Mon, 2019-03-18 13:18
Problem

The answer is Drupal's Migrate API, which is incredibly powerful but can feel overwhelming. When I migrated MSKCC.org from Drupal 6 to Drupal 8, the Migrate API was just being introduced into Drupal 8 core, and I felt more comfortable writing a custom migration script instead of using code that was still under development. Migrate API is now stable and if you are an experienced Drupal developer, you should use it.

The level of expertise required to build and maintain a Drupal 8 website has changed from Drupal 7, mainly because we are creating more ambitious digital experiences. The Drupal community struggles to simplify our flexible and sometimes complex product. My approach is to make the Webform module as flexible and robust as possible, while not forgetting that people need a simple way to start building a form. This is exactly why I include an introduction video on the Webform module's main page. Besides making the Webform module an awesome tool for experienced Drupal site builders, the Webform module needs to be welcoming to new users and make it easy for them to move their existing forms to Drupal.

Either an organization is starting from scratch and building a new Drupal site, or more commonly an organization has decided they need to provide a more ambitious digital experience and they have chosen to switch to Drupal. In both situations, we need to make it easy for someone to switch from other form builders to Webform.

The problem that needs to be addressed is…

Solution

The simplest way to migrate to the Webform module is to rebuild an external form and then import the existing data. Building a webform is fun and easy, forms are a critical aspect to most websites; it is worth taking the time needed...Read More

Categories: FLOSS Project Planets

James Duncan

Planet Apache - Mon, 2019-03-18 12:45

Somewhere in Kruezberg

Categories: FLOSS Project Planets

Python Insider: Python 3.4.10 is now available

Planet Python - Mon, 2019-03-18 12:37
Python 3.4.10 is now available.  You can download it here.

Python 3.4.10 is the final release in the Python 3.4 series.  As of this release, the 3.4 branch has been retired, no further changes to 3.4 will be accepted, and no new releases will be made.  This is standard Python policy; Python releases get five years of support and are then retired.

If you're still using Python 3.4, you should consider upgrading to the current version--3.7.2 as of this writing.  Newer versions of Python have many new features, performance improvements, and bug fixes, which should all serve to enhance your Python programming experience.

We in the Python core development community thank you for your interest in 3.4, and we wish you all the best!
Categories: FLOSS Project Planets

Jonathan Dowland: WadC 3.0

Planet Debian - Mon, 2019-03-18 11:12

blockmap.wl being reloaded (click for animation)

A couple of weeks ago I release version 3.0 of Wad Compiler, a lazy functional programming language and IDE for the construction of Doom maps.

3.0 introduces more flexible randomness with rand; two new test maps (blockmap and bsp) that demonstrate approaches to random dungeon generation; some useful data structures in the library; better Hexen support and a bunch of other improvements.

Check the release notes for the full details.

Version 3.0 of WadC is dedicated to Lu (1972-2019). RIP.

Categories: FLOSS Project Planets

leftmouseclickin: Plotting Absolute Price Oscillator (APO) Line with Python

Planet Python - Mon, 2019-03-18 10:10
Our Own Score

If you make a search on Google about APO Line, this is what you will see: Absolute Price Oscillator (APO) moving averages of a security’s price and is expressed as an absolute value. APO crossing above zero is considered bullish while crossing below zero is bearish.

This is the line we are going to plot with the help of the alpha vantage module. Below is the edit version of the Forex and Stock application. The new plot op method will plot the APO line after we have clicked on the Plot APO Line button. Just like the BBbands indicator line we can include various parameters in the get_apo method.

import json from tkinter import * import tkinter.ttk as tk from alpha_vantage.foreignexchange import ForeignExchange from alpha_vantage.techindicators import TechIndicators from alpha_vantage.timeseries import TimeSeries import matplotlib.pyplot as plt from alpha_vantage.sectorperformance import SectorPerformances win = Tk() # Create tk instance win.title("Real Forex n Stock") # Add a title win.resizable(0, 0) # Disable resizing the GUI win.configure(background='white') # change window background color selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox selectorFrame.pack(anchor = "nw", pady = 2, padx=10) currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white") currency_label.pack(anchor="w") # the currency pair label selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox selector1Frame.pack(anchor = "nw", pady = 2, padx=10) stock_label = Label(selector1Frame, text = "Select Stock / Time Interval / Series type / Moving average type / Fast Period / Slow Period :", background="white") stock_label.pack(anchor="w") # the stock label curr1 = tuple() # the tuple which will be populated by base and quote currency currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs # populate the combo box for both the base and quote currency for key in currency_list: curr1 += (key, ) # populate the stock symbol tuple f = open("stock.txt", "r") curr2 = tuple() for line in f.readlines(): curr2 += (line.replace('\n', ''),) f.close() # Create a combo box for base currency base_currency = StringVar() # create a string variable based = tk.Combobox(selectorFrame, textvariable=base_currency) based['values'] = curr1 based.pack(side = LEFT, padx=3) # Create a combo box for quote currency quote_currency = StringVar() # create a string variable quote = tk.Combobox(selectorFrame, textvariable=quote_currency) quote['values'] = curr1 quote.pack(side = LEFT, padx=3) # Create a combo box for stock items stock_symbol = StringVar() # create a string variable stock = tk.Combobox(selector1Frame, textvariable=stock_symbol) stock['values'] = curr2 stock.current(0) stock.pack(side = LEFT, padx=3) interval = tk.Combobox(selector1Frame) interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly') interval.current(0) interval.pack(side = LEFT, padx=3) price_type = tk.Combobox(selector1Frame) price_type['values'] = ('close', 'open', 'high', 'low') price_type.current(0) price_type.pack(side =LEFT, padx=3) matype_type = tk.Combobox(selector1Frame, width=37) matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)') matype_type.current(0) matype_type.pack(side =LEFT, padx=3) mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)'] # fill up the fast period and slow period combo boxes with integer ranging from 2 to 10,000 fa = tuple() for i in range(2, 10001): fa += (i, ) fast_pe = tk.Combobox(selector1Frame) fast_pe['values'] = fa fast_pe.current(0) fast_pe.pack(side=LEFT, padx=3) slow_pe = tk.Combobox(selector1Frame) slow_pe['values'] = fa slow_pe.current(0) slow_pe.pack(side=LEFT, padx=3) # create text widget area s = StringVar() # create string variable which will be used to fill up the Forex data # create currency frame and text widget to display the incoming forex data currencyFrame = Frame(win) currencyFrame.pack(side=TOP, fill=X) currency = Label(currencyFrame) currency.pack(fill=X) text_widget = Text(currency, fg='white', background='black') text_widget.pack(fill=X) s.set("Click the find button to find out the currency exchange rate") text_widget.insert(END, s.get()) buttonFrame = Frame(win) # create a bottom frame to hold the find button buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10) # first get the api key and secret from the file f = open("alpha.txt", "r") api_key = f.readline() f.close() api_key = api_key.replace('\n', '') def get_exchange_rate(): # this method will display the incoming forex data after the api called try: cc = ForeignExchange(key= api_key) from_ = based.get() to_ = quote.get() countVar = StringVar() # use to hold the character count text_widget.tag_remove("search", "1.0", "end") # cleared the hightlighted currency pair if(from_ != '' and to_ != '' and from_ != to_): data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_) exchange_rate = dict(json.loads(json.dumps(data))) count = 1 sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : " + str(exchange_rate['5. Exchange Rate']) + '\n' text_widget.delete('1.0', END) # clear all those previous text first s.set(sell_buy) text_widget.insert(INSERT, s.get()) # display forex rate in text widget pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar) text_widget.tag_configure("search", background="green") end_pos = float(pos) + float(0.7) text_widget.tag_add("search", pos, str(end_pos)) # highlight the background of the searched currency pair pos = float(pos) + 2.0 text_widget.see(str(pos)) except: print("An exception occurred") def plot_stock_echange(): try: stock_symbol_text = stock.get() # get the selected symbol if(stock_symbol_text!= ''): ts = TimeSeries(key=api_key, output_format='pandas') data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full') data['4. close'].plot() stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)' plt.title(stock_title) plt.show() except: print("An exception occurred") def plot_stock_technical(): try: stock_symbol_text = stock.get() # get the selected stock symbol if(stock_symbol_text!= ''): ti = TechIndicators(key=api_key, output_format='pandas') data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', ''))) data.plot() stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get() plt.title(stock_title) plt.show() except: print("An exception occurred") def plot_op(): # plot the Absolute price oscillator (APO) try: stock_symbol_text = stock.get() # get the selected stock symbol if(stock_symbol_text!= ''): ti = TechIndicators(key=api_key, output_format='pandas') data, meta_data = ti.get_apo(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), fastperiod = fast_pe.get(), slowperiod= slow_pe.get()) data.plot() stock_title = 'Absolute Price Oscillator (APO) for ' + stock_symbol_text + ' ' + interval.get() plt.title(stock_title) plt.show() except ValueError: print("An exception occurred") def plot_sector_performance(): sp = SectorPerformances(key=api_key, output_format='pandas') data, meta_data = sp.get_sector() data['Rank A: Real-Time Performance'].plot(kind='bar') plt.title('Real Time Performance (%) per Sector') plt.tight_layout() plt.grid() plt.show() def plot_ad(): try: stock_symbol_text = stock.get() # get the selected stock symbol if (stock_symbol_text != ''): ti = TechIndicators(key=api_key, output_format='pandas') data, meta_data = ti.get_ad(symbol=stock_symbol_text, interval=interval.get()) data.plot() stock_title = 'Chaikin A/D line values for ' + stock_symbol_text + ' ' + interval.get() plt.title(stock_title) plt.show() except: print("An exception occurred") action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair action_vid.pack(side=LEFT, padx=2) action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value action_stock_plot.pack(side=LEFT, padx=2) action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value action_technical_plot.pack(side=LEFT, padx=2) action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph action_sector_plot.pack(side=LEFT, padx=2) action_ad_plot = tk.Button(buttonFrame, text="Plot AD Line", command=plot_ad) # button used to plot the A/D line graph action_ad_plot.pack(side=LEFT, padx=2) action_ad_op = tk.Button(buttonFrame, text="Plot APO Line", command=plot_op) # button used to plot the APO line graph action_ad_op.pack(side=LEFT, padx=3) win.iconbitmap(r'ico.ico') win.mainloop()

If you run the above program and then click on the ‘Plot APO Line’ button you will see the below outcome.

Plotting the APO line for #stock with #python https://t.co/EBGN2LgGdY @chartly pic.twitter.com/NmRM3QVZ89

— TechLikin (@ChooWhei) March 18, 2019

Like, share or follow me on Twitter.

Categories: FLOSS Project Planets

Real Python: How to Build a Python GUI Application With wxPython

Planet Python - Mon, 2019-03-18 10:00

There are many graphical user interface (GUI) toolkits that you can use with the Python programming language. The big three are Tkinter, wxPython, and PyQt. Each of these toolkits will work with Windows, macOS, and Linux, with PyQt having the additional capability of working on mobile.

A graphical user interface is an application that has buttons, windows, and lots of other widgets that the user can use to interact with your application. A good example would be a web browser. It has buttons, tabs, and a main window where all the content loads.

In this article, you’ll learn how to build a graphical user interface with Python using the wxPython GUI toolkit.

Here are the topics covered:

  • Getting Started with wxPython
  • Definition of a GUI
  • Creating a Skeleton Application
  • Creating a Working Application

Let’s start learning!

Free Bonus: Click here to get access to a chapter from Python Tricks: The Book that shows you Python's best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.

Getting Started With wxPython

The wxPython GUI toolkit is a Python wrapper around a C++ library called wxWidgets. The initial release of wxPython was in 1998, so wxPython has been around quite a long time. wxPython’s primary difference from other toolkits, such as PyQt or Tkinter, is that wxPython uses the actual widgets on the native platform whenever possible. This makes wxPython applications look native to the operating system that it is running on.

PyQt and Tkinter both draw their widgets themselves, which is why they don’t always match the native widgets, although PyQt is very close.

This is not to say that wxPython does not support custom widgets. In fact, the wxPython toolkit has many custom widgets included with it, along with dozens upon dozens of core widgets. The wxPython downloads page has a section called Extra Files that is worth checking out.

Here, there is a download of the wxPython Demo package. This is a nice little application that demonstrates the vast majority of the widgets that are included with wxPython. The demo allows a developer to view the code in one tab and run it in a second tab. You can even edit and re-run the code in the demo to see how your changes affect the application.

Installing wxPython

You will be using the latest wxPython for this article, which is wxPython 4, also known as the Phoenix release. The wxPython 3 and wxPython 2 versions are built only for Python 2. When Robin Dunn, the primary maintainer of wxPython, created the wxPython 4 release, he deprecated a lot of aliases and cleaned up a lot of code to make wxPython more Pythonic and easier to maintain.

You will want to consult the following links if you are migrating from an older version of wxPython to wxPython 4 (Phoenix):

The wxPython 4 package is compatible with both Python 2.7 and Python 3.

You can now use pip to install wxPython 4, which was not possible in the legacy versions of wxPython. You can do the following to install it on your machine:

$ pip install wxpython

Note: On Mac OS X you will need a compiler installed such as XCode for the install to complete successfully. Linux may also require you to install some dependencies before the pip installer will work correctly.

For example, I needed to install freeglut3-dev, libgstreamer-plugins-base0.10-dev, and libwebkitgtk-3.0-dev on Xubuntu to get it to install.

Fortunately, the error messages that pip displays are helpful in figuring out what is missing, and you can use the prerequisites section on the wxPython Github page to help you find the information you need if you want to install wxPython on Linux.

There are some Python wheels available for the most popular Linux versions that you can find in the Extras Linux section with both GTK2 and GTK3 versions. To install one of these wheels, you would use the following command:

$ pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/ wxPython

Be sure you have modified the command above to match your version of Linux.

Definition of a GUI

As was mentioned in the introduction, a graphical user interface (GUI) is an interface that is drawn on the screen for the user to interact with.

User interfaces have some common components:

  • Main window
  • Menu
  • Toolbar
  • Buttons
  • Text Entry
  • Labels

All of these items are known generically as widgets. There are many other common widgets and many custom widgets that wxPython supports. A developer will take the widgets and arrange them logically on a window for the user to interact with.

Event Loops

A graphical user interface works by waiting for the user to do something. The something is called an event. Events happen when the user types something while your application is in focus or when the user uses their mouse to press a button or other widget.

Underneath the covers, the GUI toolkit is running an infinite loop that is called an event loop. The event loop just waits for events to occur and then acts on those events according to what the developer has coded the application to do. When the application doesn’t catch an event, it effectively ignores that it even happened.

When you are programming a graphical user interface, you will want to keep in mind that you will need to hook up each of the widgets to event handlers so that your application will do something.

There is a special consideration that you need to keep in mind when working with event loops: they can be blocked. When you block an event loop, the GUI will become unresponsive and appear to freeze to the user.

Any process that you launch in a GUI that will take longer than a quarter second should probably be launched as a separate thread or process. This will prevent your GUI from freezing and give the user a better user experience.

The wxPython framework has special thread-safe methods that you can use to communicate back to your application to let it know that the thread is finished or to give it an update.

Let’s create a skeleton application to demonstrate how events work.

Creating a Skeleton Application

An application skeleton in a GUI context is a user interface with widgets that don’t have any event handlers. These are useful for prototyping. You basically just create the GUI and present it to your stakeholders for sign-off before spending a lot of time on the backend logic.

Let’s start by creating a Hello World application with wxPython:

import wx app = wx.App() frame = wx.Frame(parent=None, title='Hello World') frame.Show() app.MainLoop()

Note: Mac users may get the following message: This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac. If you see this message and you are not running in a virtualenv, then you need to run your application with pythonw instead of python. If you are running wxPython from within a virtualenv, then see the wxPython wiki for the solution.

In this example, you have two parts: wx.App and the wx.Frame. The wx.App is wxPython’s application object and is required for running your GUI. The wx.App starts something called a .MainLoop(). This is the event loop that you learned about in the previous section.

The other piece of the puzzle is wx.Frame, which will create a window for the user to interact with. In this case, you told wxPython that the frame has no parent and that its title is Hello World. Here is what it looks like when you run the code:

Note: The application will look different when you run it on Mac or Windows.

By default, a wx.Frame will include minimize, maximize, and exit buttons along the top. You won’t normally create an application in this manner though. Most wxPython code will require you to subclass the wx.Frame and other widgets so that you can get the full power of the toolkit.

Let’s take a moment and rewrite your code as a class:

import wx class MyFrame(wx.Frame): def __init__(self): super().__init__(parent=None, title='Hello World') self.Show() if __name__ == '__main__': app = wx.App() frame = MyFrame() app.MainLoop()

You can use this code as a template for your application. However, this application doesn’t do very much, so let’s take a moment to learn a little about some of the other widgets you could add.

Widgets

The wxPython toolkit has more than one hundred widgets to choose from. This allows you to create rich applications, but it can also be daunting trying to figure out which widget to use. This is why the wxPython Demo is helpful, as it has a search filter that you can use to help you find the widgets that might apply to your project.

Most GUI applications allow the user to enter some text and press a button. Let’s go ahead and add those widgets:

import wx class MyFrame(wx.Frame): def __init__(self): super().__init__(parent=None, title='Hello World') panel = wx.Panel(self) self.text_ctrl = wx.TextCtrl(panel, pos=(5, 5)) my_btn = wx.Button(panel, label='Press Me', pos=(5, 55)) self.Show() if __name__ == '__main__': app = wx.App() frame = MyFrame() app.MainLoop()

When you run this code, your application should look like this:

The first widget you need to add is something called wx.Panel. This widget is not required, but recommended. On Windows, you are actually required to use a Panel so that the background color of the frame is the right shade of gray. Tab traversal is disabled without a Panel on Windows.

When you add the panel widget to a frame and the panel is the sole child of the frame, it will automatically expand to fill the frame with itself.

The next step is to add a wx.TextCtrl to the panel. The first argument for almost all widgets is which parent the widget should go onto. In this case, you want the text control and the button to be on top of the panel, so it is the parent you specify.

You also need to tell wxPython where to place the widget, which you can do by passing in a position via the pos parameter. In wxPython, the origin location is (0,0) which is the upper left corner of the parent. So for the text control, you tell wxPython that you want to position its top left corner 5 pixels from the left (x) and 5 pixels from the top (y).

Then you add your button to the panel and give it a label. To prevent the widgets from overlapping, you need to set the y-coordinate to 55 for the button’s position.

Absolute Positioning

When you provide exact coordinates for your widget’s position, the technique that you used is called absolute positioning. Most GUI toolkits provide this capability, but it’s not actually recommended.

As your application becomes more complex, it becomes difficult to keep track of all the widget locations and if you have to move the widgets around. Resetting all those positions becomes a nightmare.

Fortunately all modern GUI toolkits provide a solution for this, which is what you will learn about next.

Sizers (Dynamic Sizing)

The wxPython toolkit includes sizers, which are used for creating dynamic layouts. They manage the placement of your widgets for you and will adjust them when you resize the application window. Other GUI toolkits will refer to sizers as layouts, which is what PyQt does.

Here are the primary types of sizers that you will see used most often:

  • wx.BoxSizer
  • wx.GridSizer
  • wx.FlexGridSizer

Let’s add a wx.BoxSizer to your example and see if we can make it work a bit more nicely:

import wx class MyFrame(wx.Frame): def __init__(self): super().__init__(parent=None, title='Hello World') panel = wx.Panel(self) my_sizer = wx.BoxSizer(wx.VERTICAL) self.text_ctrl = wx.TextCtrl(panel) my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5) my_btn = wx.Button(panel, label='Press Me') my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5) panel.SetSizer(my_sizer) self.Show() if __name__ == '__main__': app = wx.App() frame = MyFrame() app.MainLoop()

Here you create an instance of a wx.BoxSizer and pass it wx.VERTICAL, which is the orientation that widgets are added to the sizer.

In this case, the widgets will be added vertically, which means they will be added one at a time from top to bottom. You may also set a BoxSizer’s orientation to wx.HORIZONTAL. When you do that, the widgets would be added from left to right.

To add a widget to a sizer, you will use .Add(). It accepts up to five arguments:

  • window (the widget)
  • proportion
  • flag
  • border
  • userData

The window argument is the widget to be added while proportion sets how much space relative to other widgets in the sizer this particular widget should take. By default, it is zero, which tells wxPython to leave the widget at its default proportion.

The third argument is flag. You can actually pass in multiple flags if you wish as long as you separate them with a pipe character: |. The wxPython toolkit uses | to add flags using a series of bitwise ORs.

In this example, you add the text control with the wx.ALL and wx.EXPAND flags. The wx.ALL flag tells wxPython that you want to add a border on all sides of the widget while wx.EXPAND makes the widgets expand as much as they can within the sizer.

Finally, you have the border parameter, which tells wxPython how many pixels of border you want around the widget. The userData parameter is only used when you want to do something complex with your sizing of the widget and is actually quite rare to see in practice.

Adding the button to the sizer follows the exact same steps. However, to make things a bit more interesting, I went ahead and switched out the wx.EXPAND flag for wx.CENTER so that the button would be centered on-screen.

When you run this version of the code, your application should look like the following:

If you’d like to learn more about sizers, the wxPython documentation has a nice page on the topic.

Adding an Event

While your application looks more interesting visually, it still doesn’t really do anything. For example, if you press the button, nothing really happens.

Let’s give the button a job:

import wx class MyFrame(wx.Frame): def __init__(self): super().__init__(parent=None, title='Hello World') panel = wx.Panel(self) my_sizer = wx.BoxSizer(wx.VERTICAL) self.text_ctrl = wx.TextCtrl(panel) my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5) my_btn = wx.Button(panel, label='Press Me') my_btn.Bind(wx.EVT_BUTTON, self.on_press) my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5) panel.SetSizer(my_sizer) self.Show() def on_press(self, event): value = self.text_ctrl.GetValue() if not value: print("You didn't enter anything!") else: print(f'You typed: "{value}"') if __name__ == '__main__': app = wx.App() frame = MyFrame() app.MainLoop()

The widgets in wxPython allow you to attach event bindings to them so that they can respond to certain types of events.

Note: The code block above uses f-strings. You can read all about them in Python 3’s f-Strings: An Improved String Formatting Syntax (Guide).

You want the button to do something when the user presses it. You can accomplish this by calling the button’s .Bind() method. .Bind() takes the event you want to bind to, the handler to call when the event happens, an optional source, and a couple of optional ids.

In this example, you bind your button object to the wx.EVT_BUTTON event and tell it to call on_press() when that event gets fired.

An event gets “fired” when the user does the event you have bound to. In this case, the event that you set up is the button press event, wx.EVT_BUTTON.

.on_press() accepts a second argument that you can call event. This is by convention. You could call it something else if you wanted to. However, the event parameter here refers to the fact that when this method is called, its second argument should be an event object of some sort.

Within .on_press(), you can get the text control’s contents by calling its GetValue() method. You then print a string to stdout depending on what the contents of the text control is.

Now that you have the basics out of the way, let’s learn how to create an application that does something useful!

Creating a Working Application

The first step when creating something new is to figure out what you want to create. In this case, I have taken the liberty of making that decision for you. You will learn how to create a MP3 tag editor! The next step when creating something new is to find out what packages can help you accomplish your task.

If you do a Google search for Python mp3 tagging, you will find you have several options:

  • mp3-tagger
  • eyeD3
  • mutagen

I tried out a couple of these and decided that eyeD3 had a nice API that you could use without getting bogged down with the MP3’s ID3 specification. You can install eyeD3 using pip, like this:

$ pip install eyed3

When installing this package on macOS, you may need to install libmagic using brew. Windows and Linux users shouldn’t have any issues installing eyeD3.

Designing the User Interface

When it comes to designing an interface, it’s always nice to just kind of sketch out how you think the user interface should look.

You will need to be able to do the following:

  • Open up one or more MP3 files
  • Display the current MP3 tags
  • Edit an MP3 tag

Most user interfaces use a menu or a button for opening files or folders. You can go with a File menu for this. Since you will probably want to see tags for multiple MP3 files, you will need to find a widget that can do this in a nice manner.

Something that is tabular with columns and rows would be ideal because then you can have labeled columns for the MP3 tags. The wxPython toolkit has a few widgets that would work for this, with the top two being the following:

  • wx.grid.Grid
  • wx.ListCtrl

You should use wx.ListCtrl in this case as the Grid widget is overkill, and frankly it is also quite a bit more complex. Finally, you need a button to use to edit a selected MP3’s tag.

Now that you know what you want, you can draw it up:

The illustration above gives us an idea of how the application should look. Now that you know what you want to do, it’s time to code!

Creating the User Interface

There are many different approaches when it comes to writing a new application. For example, do you need to follow the Model-View-Controller design pattern? How do you split up the classes? One class per file? There are many such questions, and as you get more experienced with GUI design, you’ll know how you want to answer them.

In your case, you really only need two classes:

  • A wx.Panel class
  • A wx.Frame class

You could argue for creating a controller type module as well, but for something like this, you really do not need it. A case could also be made for putting each class into its own module, but to keep it compact, you will create a single Python file for all of your code.

Let’s start with imports and the panel class:

import eyed3 import glob import wx class Mp3Panel(wx.Panel): def __init__(self, parent): super().__init__(parent) main_sizer = wx.BoxSizer(wx.VERTICAL) self.row_obj_dict = {} self.list_ctrl = wx.ListCtrl( self, size=(-1, 100), style=wx.LC_REPORT | wx.BORDER_SUNKEN ) self.list_ctrl.InsertColumn(0, 'Artist', width=140) self.list_ctrl.InsertColumn(1, 'Album', width=140) self.list_ctrl.InsertColumn(2, 'Title', width=200) main_sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 5) edit_button = wx.Button(self, label='Edit') edit_button.Bind(wx.EVT_BUTTON, self.on_edit) main_sizer.Add(edit_button, 0, wx.ALL | wx.CENTER, 5) self.SetSizer(main_sizer) def on_edit(self, event): print('in on_edit') def update_mp3_listing(self, folder_path): print(folder_path)

Here, you import the eyed3 package, Python’s glob package, and the wx package for your user interface. Next, you subclass wx.Panel and create your user interface. You need a dictionary for storing data about your MP3s, which you can name row_obj_dict.

Then you create a wx.ListCtrl and set it to report mode (wx.LC_REPORT) with a sunken border (wx.BORDER_SUNKEN). The list control can take on a few other forms depending on the style flag that you pass in, but the report flag is the most popular.

To make the ListCtrl have the correct headers, you will need to call .InsertColumn() for each column header. You then supply the index of the column, its label, and how wide in pixels the column should be.

The last step is to add your Edit button, an event handler, and a method. You can create the binding to the event and leave the method that it calls empty for now.

Now you should write the code for the frame:

class Mp3Frame(wx.Frame): def __init__(self): super().__init__(parent=None, title='Mp3 Tag Editor') self.panel = Mp3Panel(self) self.Show() if __name__ == '__main__': app = wx.App(False) frame = Mp3Frame() app.MainLoop()

This class is much simpler than the first one in that all you need to do is set the title of the frame and instantiate the panel class, Mp3Panel. When you are all done, your user interface should look like this:

The user interface looks almost right, but you don’t have a File menu. This makes it impossible to add MP3s to the application and edit their tags!

Let’s fix that now.

Make a Functioning Application

The first step in making your application work is to update the application so that it has a File menu because then you can add MP3 files to your creation. Menus are almost always added to the wx.Frame class, so that is the class you need to modify.

Note: Some applications have moved away from having menus in their applications. One of the first to do so was Microsoft Office when they added the Ribbon Bar. The wxPython toolkit has a custom widget that you can use to create ribbons in wx.lib.agw.ribbon.

The other type of application that has dropped menus of late are web browsers, such as Google Chrome and Mozilla Firefox. They just use toolbars nowadays.

Let’s learn how to add a menu bar to our application:

class Mp3Frame(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent=None, title='Mp3 Tag Editor') self.panel = Mp3Panel(self) self.create_menu() self.Show() def create_menu(self): menu_bar = wx.MenuBar() file_menu = wx.Menu() open_folder_menu_item = file_menu.Append( wx.ID_ANY, 'Open Folder', 'Open a folder with MP3s' ) menu_bar.Append(file_menu, '&File') self.Bind( event=wx.EVT_MENU, handler=self.on_open_folder, source=open_folder_menu_item, ) self.SetMenuBar(menu_bar) def on_open_folder(self, event): title = "Choose a directory:" dlg = wx.DirDialog(self, title, style=wx.DD_DEFAULT_STYLE) if dlg.ShowModal() == wx.ID_OK: self.panel.update_mp3_listing(dlg.GetPath()) dlg.Destroy()

Here, you add a call to .create_menu() within the class’s constructor. Then in .create_menu() itself, you will create a wx.MenuBar instance and a wx.Menu instance.

To add a menu item to a menu, you call the menu instance’s .Append() and pass it the following:

  • A unique identifier
  • The label for the new menu item
  • A help string

Next, you need to add the menu to the menubar, so you will need to call the menubar’s .Append(). It takes the menu instance and the label for menu. This label is a bit odd in that you called it &File instead of File. The ampersand tells wxPython to create a keyboard shortcut of Alt+F to open the File menu using just your keyboard.

Note: If you would like to add keyboard shortcuts to your application, then you will want to use an instance of wx.AcceleratorTable to create them. You can read more about Accerator Tables in the wxPython documentation.

To create an event binding, you will need to call self.Bind(), which binds the frame to wx.EVT_MENU. When you use self.Bind() for a menu event, you need to not only tell wxPython which handler to use, but also which source to bind the handler to.

Finally, you must call the frame’s .SetMenuBar() and pass it the menubar instance for it to be shown to the user.

Now that you have the menu added to your frame, let’s go over the menu item’s event handler, which is reproduced again below:

def on_open_folder(self, event): title = "Choose a directory:" dlg = wx.DirDialog(self, title, style=wx.DD_DEFAULT_STYLE) if dlg.ShowModal() == wx.ID_OK: self.panel.update_mp3_listing(dlg.GetPath()) dlg.Destroy()

Since you want the user to choose a folder that contains MP3s, you will want to use wxPython’s wx.DirDialog. The wx.DirDialog allows the user to only open directories.

You can set the dialog’s title and various style flags. To show the dialog, you will need to call .ShowModal(). This will cause the dialog to show modally, which means that the user won’t be able to interact with your main application while the dialog is shown.

If the user presses the dialog’s OK button, you can get the user’s path choice via the dialog’s .GetPath(). You will want to pass that path to your panel class, which you can do here by calling the panel’s .update_mp3_listing().

Finally you need to close the dialog. To close a dialog, the recommended method is to call its .Destroy().

Dialogs do have a .Close() method, but that basically just hides the dialog, and it will not destroy itself when you close your application, which can lead to weird issues such as your application now shutting down properly. It’s simpler to call .Destroy() on the dialog to prevent this issue.

Now let’s update your Mp3Panel class. You can start by updating .update_mp3_listing():

def update_mp3_listing(self, folder_path): self.current_folder_path = folder_path self.list_ctrl.ClearAll() self.list_ctrl.InsertColumn(0, 'Artist', width=140) self.list_ctrl.InsertColumn(1, 'Album', width=140) self.list_ctrl.InsertColumn(2, 'Title', width=200) self.list_ctrl.InsertColumn(3, 'Year', width=200) mp3s = glob.glob(folder_path + '/*.mp3') mp3_objects = [] index = 0 for mp3 in mp3s: mp3_object = eyed3.load(mp3) self.list_ctrl.InsertItem(index, mp3_object.tag.artist) self.list_ctrl.SetItem(index, 1, mp3_object.tag.album) self.list_ctrl.SetItem(index, 2, mp3_object.tag.title) mp3_objects.append(mp3_object) self.row_obj_dict[index] = mp3_object index += 1

Here you set the current directory to the specified folder and then you clear the list control. This keeps the list control fresh and only showing the MP3s that you are currently working on. That also means that you need to re-insert all the columns again.

Next, you’ll want to take the folder that was passed in and use Python’s glob module to search for MP3 files.

Then you can loop over the MP3s and turn them into eyed3 objects. You can do this by calling the .load() of eyed3. Assuming that the MP3s have the appropriate tags already, you can then add the artist, album, and title of the MP3 to the list control.

Interestingly, the method of adding a new row to a list control object is by calling .InsertItem() for the first column and SetItem() for all the subsequent columns.

The last step is to save off your MP3 object to your Python dictionary, row_obj_dict.

Now you need to update the .on_edit() event handler so that you can edit an MP3’s tags:

def on_edit(self, event): selection = self.list_ctrl.GetFocusedItem() if selection >= 0: mp3 = self.row_obj_dict[selection] dlg = EditDialog(mp3) dlg.ShowModal() self.update_mp3_listing(self.current_folder_path) dlg.Destroy()

The first thing you need to do is get the user’s selection by calling the list control’s .GetFocusedItem().

If the user has not selected anything in the list control, it will return -1. Assuming that the user did select something, you will want to extract the MP3 object from your dictionary and open a MP3 tag editor dialog. This will be a custom dialog that you will use to edit the artist, album, and title tags of the MP3 file.

As usual, show the dialog modally. When the dialog closes, the last two lines in .on_edit() will execute. These two lines will update the list control so it displays the current MP3 tag information that the user just edited and destroy the dialog.

Creating an Editing Dialog

The final piece of the puzzle is creating an MP3 tag editing dialog. For brevity, we will skip sketching out this interface as it is a series of rows that contains labels and text controls. The text controls should have the existing tag information pre-populated within them. You can create a label for the text controls by creating instances of wx.StaticText.

When you need to create a custom dialog, the wx.Dialog class is your friend. You can use that to design the editor:

class EditDialog(wx.Dialog): def __init__(self, mp3): title = f'Editing "{mp3.tag.title}"' super().__init__(parent=None, title=title) self.mp3 = mp3 self.main_sizer = wx.BoxSizer(wx.VERTICAL) self.artist = wx.TextCtrl( self, value=self.mp3.tag.artist) self.add_widgets('Artist', self.artist) self.album = wx.TextCtrl( self, value=self.mp3.tag.album) self.add_widgets('Album', self.album) self.title = wx.TextCtrl( self, value=self.mp3.tag.title) self.add_widgets('Title', self.title) btn_sizer = wx.BoxSizer() save_btn = wx.Button(self, label='Save') save_btn.Bind(wx.EVT_BUTTON, self.on_save) btn_sizer.Add(save_btn, 0, wx.ALL, 5) btn_sizer.Add(wx.Button( self, id=wx.ID_CANCEL), 0, wx.ALL, 5) self.main_sizer.Add(btn_sizer, 0, wx.CENTER) self.SetSizer(self.main_sizer)

Here you want to start off by sub-classing wx.Dialog and giving it a custom title based on the title of the MP3 that you are editing.

Next you can create the sizer you want to use and the widgets. To make things easier, you can create a helper method called .add_widgets() for adding the wx.StaticText widgets as rows with the text control instances. The only other widget here is the Save button.

Let’s write the add_widgets method next:

def add_widgets(self, label_text, text_ctrl): row_sizer = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, label=label_text, size=(50, -1)) row_sizer.Add(label, 0, wx.ALL, 5) row_sizer.Add(text_ctrl, 1, wx.ALL | wx.EXPAND, 5) self.main_sizer.Add(row_sizer, 0, wx.EXPAND)

add_widgets() takes the label’s text and the text control instance. It then creates a horizontally oriented BoxSizer.

Next you will create an instance of wx.StaticText using the passed-in text for its label parameter. You will also set its size to be 50 pixels wide and the default height is set with a -1. Since you want the label before the text control, you will add the StaticText widget to your BoxSizer first and then add the text control .

Finally, you want to add the horizontal sizer to the top level vertical sizer. By nesting the sizers in each other, you can design complex applications.

Now you will need to create the on_save() event handler so that you can save your changes:

def on_save(self, event): self.mp3.tag.artist = self.artist.GetValue() self.mp3.tag.album = self.album.GetValue() self.mp3.tag.title = self.title.GetValue() self.mp3.tag.save() self.Close()

Here you set the tags to the contents of the text controls and then call the eyed3 object’s .save(). Finally, you call the .Close() of the dialog. The reason you call .Close() here instead of .Destroy() is that you already call .Destroy() in the .on_edit() of your panel subclass.

Now your application is complete!

Conclusion

You learned a lot about wxPython in this article. You became familiar with the basics of creating GUI applications using wxPython.

You now know more about the following:

  • How to work with some of wxPython’s widgets
  • How events work in wxPython
  • How absolute positioning compares with sizers
  • How to create a skeleton application

Finally you learned how to create a working application, an MP3 tag editor. You can use what you learned in this article to continue to enhance this application or perhaps create an amazing application on your own.

The wxPython GUI toolkit is robust and full of interesting widgets that you can use to build cross-platform applications. You are limited by only your imagination.

Further Reading

If you would like to learn more about wxPython, you can check out some of the following links:

For more information on what else you can do with Python, you might want to check out What Can I Do with Python? If you’d like to learn more about Python’s super(), then Supercharge Your Classes With Python super() may be just right for you.

You can also download the code for the MP3 tag editor application that you created in this article if you want to study it more in depth.

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

health @ Savannah: GNU Health installer 3.4.1

GNU Planet! - Mon, 2019-03-18 09:59

Dear community

The GNU Health installer (gnuhealth-setup) has been updated to 3.4.1.

It basically fixes an issue due to the removal of the the pybarcode library from pypi (https://savannah.gnu.org/bugs/?55942)

We have also updated the documentation to always download the latest installer as the first step (https://en.wikibooks.org/wiki/GNU_Health/Installation#Downloading_and_Installing_GNU_Health)

This applies for new installations / migrations.

Best
Luis

Categories: FLOSS Project Planets

Frederic Marand: Migration FranceTVSport.fr to Drupal 8 and Symfony 4

Planet Drupal - Mon, 2019-03-18 09:03
Migration FranceTVSport.fr to Drupal 8 and Symfony 4 Submitted by Frederic Marand on Mon, 2019-03-18 14:03

The opening talk as DrupalCamp Paris 2019 was a presentation given by Thomas Jolliet (FranceTV) and yours truly about how we rebuilt FranceTV Sport to a Symfony 4 / headless Drupal 8 combo.

The most salient points of the talk are probably the "defense in depth" mechanisms we built for scalability and fault tolerance, and the business results, like -85% full page load time or +50 iOS users.

Categories: FLOSS Project Planets

James Duncan

Planet Apache - Mon, 2019-03-18 08:20

Trevor Sumner’s tweet thread about why the 737MAX tragedies aren’t a software problem is an insightful read.

Hint: it’s probably a systems problem.

Categories: FLOSS Project Planets

Podcast.__init__: Wes McKinney's Career In Python For Data Analysis

Planet Python - Mon, 2019-03-18 06:32
Python has become one of the dominant languages for data science and data analysis. Wes McKinney has been working for a decade to make tools that are easy and powerful, starting with the creation of Pandas, and eventually leading to his current work on Apache Arrow. In this episode he discusses his motivation for this work, what he sees as the current challenges to be overcome, and his hopes for the future of the industry.Summary

Python has become one of the dominant languages for data science and data analysis. Wes McKinney has been working for a decade to make tools that are easy and powerful, starting with the creation of Pandas, and eventually leading to his current work on Apache Arrow. In this episode he discusses his motivation for this work, what he sees as the current challenges to be overcome, and his hopes for the future of the industry.

Announcements
  • Hello and welcome to Podcast.__init__, the podcast about Python and the people who make it great.
  • When you’re ready to launch your next app or want to try a project you hear about on the show, you’ll need somewhere to deploy it, so take a look at our friends over at Linode. With 200 Gbit/s private networking, scalable shared block storage, node balancers, and a 40 Gbit/s public network, all controlled by a brand new API you’ve got everything you need to scale up. And for your tasks that need fast computation, such as training machine learning models, they just launched dedicated CPU instances. Go to pythonpodcast.com/linode to get a $20 credit and launch a new server in under a minute. And don’t forget to thank them for their continued support of this show!
  • Visit the site to subscribe to the show, sign up for the newsletter, and read the show notes. And if you have any questions, comments, or suggestions I would love to hear them. You can reach me on Twitter at @Podcast__init__ or email hosts@podcastinit.com)
  • To help other people find the show please leave a review on iTunes and tell your friends and co-workers
  • Join the community in the new Zulip chat workspace at pythonpodcast.com/chat
  • Check out the Practical AI podcast from our friends at Changelog Media to learn and stay up to date with what’s happening in AI
  • You listen to this show to learn and stay up to date with the ways that Python is being used, including the latest in machine learning and data analysis. For even more opportunities to meet, listen, and learn from your peers you don’t want to miss out on this year’s conference season. We have partnered with O’Reilly Media for the Strata conference in San Francisco on March 25th and the Artificial Intelligence conference in NYC on April 15th. Here in Boston, starting on May 17th, you still have time to grab a ticket to the Enterprise Data World, and from April 30th to May 3rd is the Open Data Science Conference. Go to pythonpodcast.com/conferences to learn more and take advantage of our partner discounts when you register.
  • Your host as usual is Tobias Macey and today I’m interviewing Wes McKinney about his contributions to the Python community and his current projects to make data analytics easier for everyone
Interview
  • Introductions
  • How did you get introduced to Python?
  • You have spent a large portion of your career on building tools for data science and analytics in the Python ecosystem. What is your motivation for focusing on this problem domain?
  • Having been an open source author and contributor for many years now, what are your current thoughts on paths to sustainability?
  • What are some of the common challenges pertaining to data analysis that you have experienced in the various work environments and software projects that you have been involved in?
    • What area(s) of data science and analytics do you find are not receiving the attention that they deserve?
  • Recently there has been a lot of focus and excitement around the capabilities of neural networks and deep learning. In your experience, what are some of the shortcomings or blind spots to that class of approach that would be better served by other classes of solution?
  • Your most recent work is focused on the Arrow project for improving interoperability across languages. What are some of the cases where a Python developer would want to incorporate capabilities from other runtimes?
    • Do you think that we should be working to replicate some of those capabilities into the Python language and ecosystem, or is that wasted effort that would be better spent elsewhere?
  • Now that Pandas has been in active use for over a decade and you have had the opportunity to get some space from it, what are your thoughts on its success?
    • With the perspective that you have gained in that time, what would you do differently if you were starting over today?
  • You are best known for being the creator of Pandas, but can you list some of the other achievements that you are most proud of?
  • What projects are you most excited to be working on in the near to medium future?
  • What are your grand ambitions for the future of the data science community, both in and outside of the Python ecosystem?
  • Do you have any parting advice for active or aspiring data scientists, or resources that you would like to recommend?
Keep In Touch Picks Links

The intro and outro music is from Requiem for a Fish The Freak Fandango Orchestra / CC BY-SA

Categories: FLOSS Project Planets

Third & Grove: AEM vs. Drupal (AEM Wins in Only 3 Cases)

Planet Drupal - Mon, 2019-03-18 06:00
AEM vs. Drupal (AEM Wins in Only 3 Cases) justin Mon, 03/18/2019 - 06:00
Categories: FLOSS Project Planets

Zato Blog: HTTP Method and Accept headers

Planet Python - Mon, 2019-03-18 05:38

Zato 3.1 includes new means to manage access to REST services based on input Method and Accept headers in HTTP requests - here is how they can be employed in practice.

A bit of background

Prior to Zato 3.1, one could always build a REST API reacting to individual HTTP verbs by implementing handle_VERB methods in services, such as:

class MyService(Service): def handle_GET(self): # Reacts to GET requests pass def handle_POST(self): # Reacts to POST requests pass # Any other handle_VERB method will be used accordingly

This works and will continue to work as expected in all future Zato versions.

However, one aspect of it is that, if one uses SimpleIO, keeping all handler methods in the same service means that all of them share the same SIO definition which is not always desirable - for instance, input to POST may be unrelated to input that DELETE receives.

REST channel URL paths

In Zato 3.1 and newer, it is possible to create REST channels that have the same URL path but different services mounted on each channel, separately for each HTTP verb requires.

That is, whereas previously it was a single service with multiple handle_VERB methods, now it can be a set of services, each reacting to a different HTTP verb and all of them mounted on the same URL path.

In a way, this was supported previously but, if handle_VERB methods were not used, URL paths had to be distinct, e.g.

GET /api/user DELETE /api/user/delete POST /api/user/create

In 3.1+, this can be simplified to:

GET /api/user DELETE /api/user POST /api/user

Now, each of the combination of verb + path may be unique for a REST channel while previously each channel needed to have its own URL path.

Moreover, because each channel may have its own separate service, it also means that each service may have its own SimpleIO definition and that the service becomes less tied to REST.

HTTP Accept headers

This is a completely new feature in 3.1 which lets one have distinct REST channels depending on the requests's Accept headers.

For instance, let's say that we would like to process incoming invoices under POST /api/invoice but we would like to have two services reacting to the same endpoint, one for JSON and now for PDF invoices.

This can be achieved by configuring HTTP Accept headers in their channels, as below - note that the method and URL path are the same in both cases yet HTTP Accept and services are different because each service reacts to a different value of HTTP Accept:

HTTP Accept header patterns

We can go one better and take advantage of Accept header patterns - with an asterisk meaning any character - this will configure the channel to process requests matching any value that fits in with the pattern, e.g. text/* will mean text/csv, text/xml or anything that starts with text/.

However, seeing as it can be a number of input MIME types, at this point we may need to know what the actual value was - this can be extracted from the WSGI environment via self.wsgi_environ.

Summary

Zato 3.1 saw improvements and backward-compatible changes to how REST channels can be built.

It will now support more use-cases, such as single URL path channels with different HTTP verbs and independent SimpleIO definitions or HTTP Accept headers different for each channel.

In turn, this lets one build REST APIs that are more flexible and elastic in their design to react to different input criteria.

Categories: FLOSS Project Planets

Django Weblog: Django 2.2 release candidate 1 released

Planet Python - Mon, 2019-03-18 04:40

Django 2.2 release candidate 1 is the final opportunity for you to try out the salmagundi of new features before Django 2.2 is released.

The release candidate stage marks the string freeze and the call for translators to submit translations. Provided no major bugs are discovered that can't be solved in the next two weeks, Django 2.2 will be released on or around April 1. Any delays will be communicated on the django-developers mailing list thread.

Please use this opportunity to help find and fix bugs (which should be reported to the issue tracker). You can grab a copy of the package from our downloads page or on PyPI.

The PGP key ID used for this release is Carlton Gibson: E17DF5C82B4F9D00.

Categories: FLOSS Project Planets

Interview with Svetlana Rastegina

Planet KDE - Mon, 2019-03-18 04:00

Could you tell us something about yourself?

My name is Svetlana Rastegina. I work in graphic design and 3D modeling. I have been painting since I was twelve. I have a background in watercolour painting.

Do you paint professionally, as a hobby artist, or both?

I’m a professional graphic artist. Although, sometimes I get carried away drawing for myself.

What genre(s) do you work in?

I work in various genres: fantasy, cartoons, conceptual, children’s illustration. Among these genres, my favorite is fantasy.

Whose work inspires you most — who are your role models as an artist?

I don’t have a single favorite artist. The creativity of many artists appeals to me and I try to learn the best from each of them. Among Russian illustrators I like Vladyslav Yerko.

How and when did you get to try digital painting for the first time?

For the first time I tried digital painting at the university, where I studied environment design. I started drawing on the tablet in 2006.

What makes you choose digital over traditional painting?

I think prefer working with digital painting because it is more dynamic and provides more freedom.

How did you find out about Krita?

I prefer software with an open source license. One of my friends suggested to try it and it met my needs.

What was your first impression?

It was very easy to start working in Krita. I fell in love with it almost immediately.

What do you love about Krita?

I like the big set of brushes and filters. And above all I like stability.

What do you think needs improvement in Krita? Is there anything that really annoys you?

I would like a bigger dynamic menu to have more brushes on hand.

What sets Krita apart from the other tools that you use?

Krita has one of the most convenient interface and tool sets for working with illustrations.

If you had to pick one favourite of all your work done in Krita so far, what would it be, and why?

It is very difficult to choose only one project. From my recent works I would pick the Cellist, because I like to work in the fantasy genre and monochrome colors.

What techniques and brushes did you use in it?

I work in the technique of a smoothed dab with the subsequent parts refinement, often using texture technique. I make multiple layers, with separate layer for sketching, shadows, highlights and some details. Some brushes used in the work: Basic, Blender blur, Dry Bristles, Chalc Grainy, Blender Textured Soft.

Where can people see more of your work?

If you want to know more about my works you can visit my website: https://svyr.pro/
Other resources where you can find my works:
https://www.artstation.com/svyr
https://blenderartists.org/u/svyr/activity

Anything else you’d like to share?

I am always open for communication and new projects.
https://www.facebook.com/svetlana.rastegina

Categories: FLOSS Project Planets

codingdirectional: Create a sports score application with python

Planet Python - Mon, 2019-03-18 03:02

Hello and welcome back. In this chapter, we will create a small sports score application with the help of the sports.py module. We will create a simple application to retrieve the score of the NBA result for any two particular teams and prints it on the tkinter’s text widget. Before we start, you will need to download the sports.py module to your own computer. Since the module is on pypi.org all you need is to open up your windows command prompt and type in below line to download that module! As I have mentioned earlier, I am now using visual studio 2019 to develop this new python project.

pip install sports.py

Now just start the visual studio 2019 then type the below code into the code editor.

import sports import json from tkinter import * import tkinter.ttk as tk win = Tk() # Create tk instance win.title("NBA") # Add a title win.resizable(0, 0) # Disable resizing the GUI win.configure(background='white') # change window background color selectorFrame = Frame(win, background="white") # create top frame to hold team 1 vs team 2 combobox selectorFrame.pack(anchor = "nw", pady = 2, padx=10) match_label = Label(selectorFrame, text = "Select Team 1 vs Team 2 :", background="white") match_label.pack(anchor="w") # the team label # Create a combo box for team 1 team1 = tk.Combobox(selectorFrame) team1.pack(side = LEFT, padx=3) # Create a combo box for team 2 team2 = tk.Combobox(selectorFrame) team2.pack(side = LEFT, padx=3) s = StringVar() # create string variable # create match frame and text widget to display the incoming match data matchFrame = Frame(win) matchFrame.pack(side=TOP) match = Label(matchFrame) match.pack() text_widget = Text(match, fg='white', background='black') text_widget.pack() s.set("Click the find button to find out the match result") text_widget.insert(END, s.get()) buttonFrame = Frame(win) # create a bottom frame to hold the find button buttonFrame.pack(side = BOTTOM, fill=X, pady = 6) # fill up the combo boxes with the team name data from the text file team_tuple = tuple() f = open("TextFile1.txt", "r") for line in f.readlines(): line = line.replace('\n', '') team_tuple += (line, ) f.close() team1["values"] = team_tuple team1.current(1) team2["values"] = team_tuple team2.current(0) def get_match(): # return the recent match of team 1 vs team 2 try: match = sports.get_match(sports.BASKETBALL, team1.get(), team2.get()) text_widget.delete('1.0', END) # clear all those previous text first s.set(match) text_widget.insert(INSERT, s.get()) # display team match data in text widget except: print("An exception occurred") action_vid = tk.Button(buttonFrame, text="Find", command=get_match) # button used to find out the team match data action_vid.pack() win.mainloop()

Select the debug tab then start debugging the program.

Create a #sport score data application with #python program pic.twitter.com/a8Ln2v31nY

— TechLikin (@ChooWhei) March 18, 2019

In the next chapter, we will further modify this sports score application, maybe with other module and API because there are a few shortages in this current module.

Categories: FLOSS Project Planets

Mike Driscoll: PyDev of the Week: Bruno Rocha

Planet Python - Mon, 2019-03-18 01:05

This week we welcome Bruno Rocha (@rochacbruno) as our PyDev of the Week! Bruno works for Red Hat and participates in the Python, Flask and Rust communities. You can see some of his projects over on Github or check out some of his writings on Medium. Let’s take a few moments to get to know Bruno better!

Can you tell us a little about yourself (hobbies, education, etc):

I’m Bruno Rocha, Software Engineer from São Paulo, Brazil.

I started playing with computers at a very young age when I was 12 when my mother gave me an old IBM XT 5160. After a few days playing DOOM and studying LOTUS 123 worksheets, I naturally became the computer boy in the family. I did a course of MS.DOS 6.22 (the novelty of that time) and learned to program some things with BASIC and dBase, a few years later the web appeared in Brazil and I started to make HTML sites with CGI in Perl and also to create programs with macros in MS Access 95.

I worked for some years as an instructor in basic computer courses, some jobs as a web designer, I also worked with network installation, PC building, and in 1998 I met Linux through Conectiva (A Brazilian Red Hat based distro). I got involved with Open Source and Linux and then I became sysadmin in hybrid networks with Linux and Windows NT.

Years later I joined the University of Information Systems and I graduated, during graduation I fell in love with programming and since then I have been working with software development, started some small business (in the days when we did not call it “startup”), I worked for Palm Inc. developed drivers and sales force systems for Palm OS with C, developed portals and CMS for several large companies in Brazil, taught online Python courses, worked in the Data Science team of the largest Job board in Brazil and since 2016 I have been dedicated to Quality Engineering and Test Automation at Red Hat.

Besides software and computers, I am vegetarian since I was born, and vegan for more than 15 years. I have been very active in animal rights activism movements and also in the rescue of abandoned animals (currently taking care of 32 rescued animals).

In my free time I love cooking vegan food but my favorite hobby is road cycling, I have participated in some vintage bike races with my Bianchi 1973 and my Caloi-10 1980, recently I became father of a boy, Erik is 3 months old and life has changed a little and since then my favorite hobby has been to sleep when I can.

Why did you start using Python?

In the early 2000s I was focused on bringing Linux to the desktops of the companies for which I provided SysAdmin services, Knoppix (Linux from Live CD) came out, and in Brazil I got involved with the community around the Linux distribution called Kurumin Linux. The innovation in this Linux was the so-called “Magic Icons” many written in Python and one of these icons led to an interactive tutorial on Python, that’s when I had my first contact and then I started contributing to this community.

The idea of bringing Linux to Desktops failed, but in compensation I learned Python that very soon became useful in other areas with the emergence of web frameworks like Pylons, Turbogears and Django.

Despite working with different technologies like .NET, PHP to pay the bills every day I got more involved with Python and adopted it as my preferred language for projects, around 2008 I became a core committer and one of Web2py’s most active contributors. I started organizing meetups, talking at many community events and large conferences, in 2012 I co-authored a book on web development with Python and in same year I was nominated a Fellow member of the Python Software Foundation where I still work in 2 workgroups.

Since 2008 I have worked exclusively with Python in different areas, teaching, maintaining some open-source libraries, more heavily involved in web with Django and Flask and more recently focused on automation of tests and Quality Engineering.

What other programming languages do you know and which is your favorite?

I am fluent in C, C#, Javascript, Bash, PHP, Perl, Lua, Python and currently learning Rust.

In addition to Python (of course) because it is the technology and community that has supported me for almost 15 years, if I had to choose just one language I would choose Rust because it is an innovative language, it gives me the feeling that I am doing things in the right way, it’s very challenging and everything indicates that it will have a bright future! (or rather, rusty future)

What projects are you working on now?

I created some open-source projects mostly around Flask, one of them is Flasgger (horrible name) which is an extension to create Swagger APIs. I have also created a CMS with Flask and NoSQL called Quokka CMS, and some other extensions for Flask that are currently being maintained by the community since I am not having much time available to devote myself to these projects.

The only project I actively maintain is a library called Dynaconf, it is a Python configuration manager, with extensions for Django and Flask, which aims to facilitate the management of settings dynamically with support for various file formats, environments and databases.

Professionally I work on Pulp Project, which is part of Red Hat Satellite and Ansible Galaxy. Pulp is a Django application that controls the distribution of software packages. My role is on development of Pulp-Smash a functional testing framework for exercising Pulp.

In addition I have been teaching Python and Quality Engineering, I share some stuff on CursoDePython YouTube channel (in Portuguese) and co-host the Castálio podcast.

Which Python libraries are your favorite (core or 3rd party)?

Inside the standard library I greatly admire Functools and Contextlib, I really like meta programming and I have used these 2 libraries in almost all of my projects.

3rd party I would like to mention Poetry, I believe that Poetry is the “package manager” that every Pythonist has always dreamed of, and this tool needs more attention because currently it is the one that best solve the problems of dependencies and distribution.

Is there anything else you’d like to say?

I want to use this space to thank immensely all the “social developers,” people who devote their time and wisdom to creating social impact projects that are already changing the world, technology is a good source of income but the most important thing is “transformation of the world” and what still gives me energy for open-source is knowing that the little I do with open-source can somehow help social impact projects.

And last but not the least; Go Vegan!.

Thanks for doing the interview, Bruno!

Categories: FLOSS Project Planets

leftmouseclickin: Plotting the Chaikin AD line graph

Planet Python - Mon, 2019-03-18 00:02
Our Own Score

In this chapter, we will create a method to plot the Chaikin AD line graph with the help from the alpha vantage module. The Accumulation Distribution Line (ADL) is used by Chaikin Oscillator to measure the movements of a stock.

We will include a button to call the plot ad method to plot the AD line graph.

import json from tkinter import * import tkinter.ttk as tk from alpha_vantage.foreignexchange import ForeignExchange from alpha_vantage.techindicators import TechIndicators from alpha_vantage.timeseries import TimeSeries import matplotlib.pyplot as plt from alpha_vantage.sectorperformance import SectorPerformances win = Tk() # Create tk instance win.title("Real Forex n Stock") # Add a title win.resizable(0, 0) # Disable resizing the GUI win.configure(background='white') # change window background color selectorFrame = Frame(win, background="white") # create the top frame to hold base and quote currency combobox selectorFrame.pack(anchor = "nw", pady = 2, padx=10) currency_label = Label(selectorFrame, text = "Select base currency / quote currency :", background="white") currency_label.pack(anchor="w") # the currency pair label selector1Frame = Frame(win, background="white") # create the middle frame to hold base and quote currency combobox selector1Frame.pack(anchor = "nw", pady = 2, padx=10) stock_label = Label(selector1Frame, text = "Select Stock :", background="white") stock_label.pack(anchor="w") # the stock label curr1 = tuple() # the tuple which will be populated by base and quote currency currency_list = ['AUD', 'BCH', 'BNB', 'BND', 'BTC', 'CAD', 'CHF', 'CNY', 'EOS', 'EUR', 'ETH', 'GBP', 'HKD', 'JPY', 'LTC', 'NZD', 'MYR', 'TRX', 'USD', 'USDT', 'XLM', 'XRP'] # major world currency pairs # populate the combo box for both the base and quote currency for key in currency_list: curr1 += (key, ) # populate the stock symbol tuple f = open("stock.txt", "r") curr2 = tuple() for line in f.readlines(): curr2 += (line.replace('\n', ''),) f.close() # Create a combo box for base currency base_currency = StringVar() # create a string variable based = tk.Combobox(selectorFrame, textvariable=base_currency) based['values'] = curr1 based.pack(side = LEFT, padx=3) # Create a combo box for quote currency quote_currency = StringVar() # create a string variable quote = tk.Combobox(selectorFrame, textvariable=quote_currency) quote['values'] = curr1 quote.pack(side = LEFT, padx=3) # Create a combo box for stock items stock_symbol = StringVar() # create a string variable stock = tk.Combobox(selector1Frame, textvariable=stock_symbol) stock['values'] = curr2 stock.current(0) stock.pack(side = LEFT, padx=3) interval = tk.Combobox(selector1Frame) interval['values'] = ('1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly') interval.current(0) interval.pack(side = LEFT, padx=3) price_type = tk.Combobox(selector1Frame) price_type['values'] = ('close', 'open', 'high', 'low') price_type.current(0) price_type.pack(side =LEFT, padx=3) matype_type = tk.Combobox(selector1Frame, width=37) matype_type['values'] = ('Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)') matype_type.current(0) matype_type.pack(side =LEFT, padx=3) mattype_list = ['Simple Moving Average (SMA)', 'Exponential Moving Average (EMA)', 'Weighted Moving Average (WMA)', 'Double Exponential Moving Average (DEMA', 'Triple Exponential Moving Average (TEMA)', 'Triangular Moving Average (TRIMA', 'T3 Moving Average', 'Kaufman Adaptive Moving Average (KAMA)', ' MESA Adaptive Moving Average (MAMA)'] s = StringVar() # create string variable which will be used to fill up the Forex data # create currency frame and text widget to display the incoming forex data currencyFrame = Frame(win) currencyFrame.pack(side=TOP) currency = Label(currencyFrame) currency.pack(fill=X) text_widget = Text(currency, fg='white', background='black') text_widget.pack(fill=X) s.set("Click the find button to find out the currency exchange rate") text_widget.insert(END, s.get()) buttonFrame = Frame(win) # create a bottom frame to hold the find button buttonFrame.pack(side = BOTTOM, fill=X, pady = 6, padx=10) # first get the api key and secret from the file f = open("alpha.txt", "r") api_key = f.readline() f.close() api_key = api_key.replace('\n', '') def get_exchange_rate(): # this method will display the incoming forex data after the api called try: cc = ForeignExchange(key= api_key) from_ = based.get() to_ = quote.get() countVar = StringVar() # use to hold the character count text_widget.tag_remove("search", "1.0", "end") # cleared the hightlighted currency pair if(from_ != '' and to_ != '' and from_ != to_): data, _ = cc.get_currency_exchange_rate(from_currency=from_, to_currency=to_) exchange_rate = dict(json.loads(json.dumps(data))) count = 1 sell_buy = str(count) + ".) Pair : " + exchange_rate['1. From_Currency Code'] + "(" + exchange_rate['2. From_Currency Name'] + ")" + " / " + exchange_rate['3. To_Currency Code']+"(" + exchange_rate['4. To_Currency Name'] + ") : " + str(exchange_rate['5. Exchange Rate']) + '\n' text_widget.delete('1.0', END) # clear all those previous text first s.set(sell_buy) text_widget.insert(INSERT, s.get()) # display forex rate in text widget pos = text_widget.search(from_, "1.0", stopindex="end", count=countVar) text_widget.tag_configure("search", background="green") end_pos = float(pos) + float(0.7) text_widget.tag_add("search", pos, str(end_pos)) # highlight the background of the searched currency pair pos = float(pos) + 2.0 text_widget.see(str(pos)) except: print("An exception occurred") def plot_stock_echange(): try: stock_symbol_text = stock.get() # get the selected symbol if(stock_symbol_text!= ''): ts = TimeSeries(key=api_key, output_format='pandas') data, meta_data = ts.get_intraday(symbol=stock_symbol_text, interval='1min', outputsize='full') data['4. close'].plot() stock_title = 'Intraday Times Series for the ' + stock_symbol_text + ' stock (1 min)' plt.title(stock_title) plt.show() except: print("An exception occurred") def plot_stock_technical(): try: stock_symbol_text = stock.get() # get the selected stock symbol if(stock_symbol_text!= ''): ti = TechIndicators(key=api_key, output_format='pandas') data, meta_data = ti.get_bbands(symbol=stock_symbol_text, interval=interval.get(), series_type=price_type.get(), matype=mattype_list.index(matype_type.get()), time_period=int(interval.get().replace('min', ''))) data.plot() stock_title = 'BBbands indicator for ' + stock_symbol_text + ' ' + interval.get() plt.title(stock_title) plt.show() except: print("An exception occurred") def plot_sector_performance(): sp = SectorPerformances(key=api_key, output_format='pandas') data, meta_data = sp.get_sector() data['Rank A: Real-Time Performance'].plot(kind='bar') plt.title('Real Time Performance (%) per Sector') plt.tight_layout() plt.grid() plt.show() def plot_ad(): # plot the AD line try: stock_symbol_text = stock.get() # get the selected stock symbol if (stock_symbol_text != ''): ti = TechIndicators(key=api_key, output_format='pandas') data, meta_data = ti.get_ad(symbol=stock_symbol_text, interval=interval.get()) data.plot() stock_title = 'Chaikin A/D line values for ' + stock_symbol_text + ' ' + interval.get() plt.title(stock_title) plt.show() except: print("An exception occurred") action_vid = tk.Button(buttonFrame, text="Calculate Exchange Rate", command=get_exchange_rate) # button used to find out the exchange rate of currency pair action_vid.pack(side=LEFT, padx=2) action_stock_plot = tk.Button(buttonFrame, text="Plot Stock", command=plot_stock_echange) # button used to plot the intra-minute stock value action_stock_plot.pack(side=LEFT, padx=2) action_technical_plot = tk.Button(buttonFrame, text="Plot Technical", command=plot_stock_technical) # button used to plot the 60 minutes stock technical value action_technical_plot.pack(side=LEFT, padx=2) action_sector_plot = tk.Button(buttonFrame, text="Plot Sector Performance", command=plot_sector_performance) # button used to plot the sector performance graph action_sector_plot.pack(side=LEFT, padx=2) action_ad_plot = tk.Button(buttonFrame, text="Plot AD Line", command=plot_ad) # button used to plot the A/D line graph action_ad_plot.pack(side=LEFT, padx=2) win.iconbitmap(r'ico.ico') win.mainloop()

Anticipating trend changes in the Accumulation Distribution Line can help chartists anticipate trend changes in the underlying security.

Let us take a look at the Chaikin AD line of one the stocks below within the time interval of 60 minutes.

Plotting the Chaikin AD line graph of a #stock with a #python application @chartly pic.twitter.com/BLleM87lGY

— TechLikin (@ChooWhei) March 18, 2019

I am thinking of putting this project online soon and this project will get updated weekly with the latest feature, so stay tune. Like, share or follow me on Twitter if you want more Forex and Stock programming tips.

Categories: FLOSS Project Planets

Montreal Python User Group: Montréal-Python 74: Call for speakers - Virtual Echo

Planet Python - Mon, 2019-03-18 00:00

Spring is upon us and it's time for pythonistas to gather and discuss the latest news and their latest projects.

For this occasion we are looking for speakers who would like to share their latest discoveries. This is the best opportunity to reach out to the Montreal python community.

To submit your talk, write us at the following address: mtlpyteam@googlegroups.com or join us on Slack at http://montrealpython.org/en/slackin.

When

Monday xx 2019 at 6pm

Where

Shopify, 490 rue de la Gauchetière Montréal, Québec (map) https://goo.gl/maps/FccEH2n7EPm

Schedule

6:00PM - Doors open 6:30PM - Presentations 8:00PM - End of the event 8:15PM - Benelux

Categories: FLOSS Project Planets

Justin Mason: Links for 2019-03-17

Planet Apache - Sun, 2019-03-17 19:58
  • 2-hour-long meetings can impair cognitive functioning

    ‘Study shoes three people in a conference room over 2 hours can result in a Co2 level that can impair cognitive functioning. Ie. If you’re making decisions at the end of the meeting, you’re mentally less qualified to do so.’ Well, I’d say that fatigue could also result in this, but it’s interesting to see how unhealthy the typical office environment can be. (via Jeff Dean)

    (tags: via:jeffdean meetings work offices brain co2 cognition)

Categories: FLOSS Project Planets

Pages