The API in Detail

0
3398
25 min read

In this article by Hugo Solis, author of book, Kivy Cookbook, we will learn to create simple API with the help of App class. We will also learn how to load images of asynchronous data, parsing of data, exception handling, utils applications and use of factory objects. Working of audio, video and camera in Kivy will be explained in this article. Also we will learn text manipulation and and usage of spellcheck option. We will see how to add different effects to the courser in this article.

(For more resources related to this topic, see here.)

Kivy is actually an API for Python, which lets us create cross-platform apps. An application programming interface (API) is a set of routines, protocols, and tools to build software applications. Generally, we call Kivy as a framework because it also has procedures and instructions, such as the Kv language, which are not present in Python. Frameworks are environments that come with support programs, compilers, code libraries, tool sets, and APIs.

In this article, we want to review the Kivy API reference. We will go through some useful classes of the API. Every time we import a Kivy package, we will be dealing with an API. Even though the usual imports are from kivy.uix, there are more options and classes in the Kivy API. The Kivy developers have created the API reference, which you can refer to online at http://kivy.org/docs/api-kivy.html for an exhaustive information.


Getting to know the API

Our starting point is going to be the App class, which is the base to create Kivy applications. In this recipe, we are going to create a simple app that uses some resources from this class.

Getting ready

It is important to see the role of the App class in the code.

How to do it…

To complete this recipe, we will create a Python file to make the resources present in the App class. Let’s follow these steps:

  1. Import the kivy package.
  2. Import the App package.
  3. Import the Widget package.
  4. Define the MyW() class.
  5. Define the e1App() class instanced as App.
  6. Define the build() method and give an icon and a title to the app.
  7. Define the on_start() method.
  8. Define the on_pause() method.
  9. Define the on_resume() method.
  10. Define the on_stop() method.
  11. End the app with the usual lines.
    import kivy
    from kivy.app import App
    from kivy.uix.widget import Widget
    
    class MyW(Widget):
        pass
    
    class e1App(App):
    
        def build(self):
            self.title = 'My Title'
            self.icon = 'f0.png'
            returnMyW()
    
        def on_start(self):
            print("Hi")
            return True
    
        def on_pause(self):
            print("paused")
            return True
    
        def on_resume(self):
            print("active")
            pass
    
        def on_stop(self):
            print("Bye!")
            pass
    
    if __name__ == '__main__':
        e1App().run()
    

How it works…

In the second line, we import the most common kivy package. This is the most used element of the API because it permits to create applications. The third line is an importation from kivy.uix that could be the second most used element, because the majority of the widgets are in there.

In the e1app class, we have the usual build() method where we have the line:

self.title = 'My Title'

We are providing a title to the app. As you can remember, the default title should be e1 because of the class’s name, but now we are using the title that we want. We have the next line:

self.icon = 'f0.png'

We are giving the app an icon. The default is the Kivy logo, but with this instruction, we are using the image in the file f0.png. In addition, we have the following method:

 def on_start(self):
       print("Hi")
       return True

It is in charge of all actions performed when the app starts. In this case, it will print the word Hi in the console. The method is as follows:

  def on_pause(self):
       print("paused")
       return True

This is the method that is performed when the app is paused when it is taken off from RAM. This event is very common when the app is running in a mobile device. You should return True if your app can go into pause mode, otherwise return False and your application will be stopped. In this case, we will print the word paused in the console, but it is very important that you save important information in the long-term memory, because there can be errors in the resume of the app and most mobiles don’t allow real multitasking and pause apps when switching between them. This method is used with:

def on_resume(self):
       print("active")
       pass

The on_resume method is where we verify and correct any error in the sensible data of the app. In this case, we are only printing the word active in the console. The last method is:

  def on_stop(self):
       print("Bye!")
       pass

It is where all the actions are performed before the app closes. Normally, we save data and take statistics in this method, but in this recipe, we just say Bye! in the console.

There’s more…

There is another method, the load_kv method, that you can invoke in the build method, which permits to make our own selection of the KV file to use and not the default one. You only have to add follow line in the build() method:

self.load_kv(filename='e2.kv')

See also

The natural way to go deeper in this recipe is to take a look at the special characteristics that the App has for the multiplatform support that Kivy provides.

Using the asynchronous data loader

An asynchronous data loader permits to load images even if its data is not available. It has diverse applications, but the most common is to load images from the Internet, because this makes our app always useful even in the absence of Web connectivity. In this recipe, we will generate an app that loads an image from the Internet.

Getting ready

We did image loading from the Internet.

We need an image from the Web, so find it and grab its URL.

How to do it…

We need only a Python file and the URL in this recipe. To complete the recipe:

  1. Import the usual kivy package.
  2. Import the Image and Loader packages.
  3. Import the Widget package.
  4. Define the e2App class.
  5. Define the _image_Loaded() method, which loads the image in the app.
  6. Define the build() method.
  7. In this method, load the image in a proxy image.
  8. Define the image variable instanced as Image().
  9. Return the image variable to display the load image:
    import kivy
    kivy.require('1.9.0')
    
    from kivy.app import App
    from kivy.uix.image import Image
    from kivy.loader import Loader
    
    class e2App(App):
    
        def _image_loaded(self, proxyImage):
            if proxyImage.image.texture:
                self.image.texture = proxyImage.image.texture
    
        def build(self):
            proxyImage = Loader.image( 
            'http://iftucr.org/IFT/ANL_files/artistica.jpg')
            proxyImage.bind(on_load=self._image_loaded)
            self.image = Image()
            return self.image
    
    if __name__ == '__main__':
        e2App().run()
    

How it works…

The line that loads the image is:

       proxyImage = Loader.image(
       'http://iftucr.org/IFT/ANL_files/artistica.jpg')

We assign the image to the proxyImage variable because we are not sure if the image exists or could be retrieved from the Web. We have the following line:

proxyImage.bind(on_load=self._image_loaded)

We bind the event on_load to the variable proxyImage. The used method is:

  def _image_loaded(self, proxyImage):
       if proxyImageifproxyImage.image.texture:
       self.image.texture =     proxyImage.image.texture

It verifies whether the image is loaded or not; if not, then it does not change the image. This is why, we said that this will load in an asynchronous way.

There’s more…

You can also load an image from a file in the traditional way. We have the following line:

      proxyImage = Loader.image(
       'http://iftucr.org/IFT/ANL_files/artistica.jpg')

Replace the preceding line with:

proxyImage = Loader.image('f0.png')

Here, f0.png is the name of the file to load.

Logging objects

The log in any software is useful for many aspects, one of them being exception handling. Kivy is always logging information about its performance. It creates a log file of every running of our app. Every programmer knows how helpful logging is for software engineering. In this recipe, we want to show information of our app in that log.

How to do it…

We will use a Python file with the MyW() usual class where we will raise an error and display it in the Kivy log. To complete the recipe, follow these steps:

  1. Import the usual kivy package.
  2. Import the Logger packages.
  3. Define the MyW() class.
  4. Trigger an info log.
  5. Trigger a debug log.
  6. Perform an exception.
  7. Trigger an exception log:
    import kivy
    kivy.require('1.9.0')
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.logger import Logger
    
    class MyW(Widget):
       Logger.info('MyW: This is an info message.')
       Logger.debug('MyW: This is a debug message.')
       try:
           raise Exception('exception')
       except Exception:
           Logger.exception('Something happened!')
    class e3App(App):
    
       def build(self):
           return MyW()
    
    if __name__ == '__main__':
       e3App().run()

How it works…

In this recipe, we are creating three logs. The first in the line is:

   Logger.info('MyW: This is an info message.')

This is an info log, which is associated just with the supplementary information. The label MyW is just a convention, but you could use it in whatever way you like. Using the convention, we track where the log was performed in the code. We will see a log made by that line as:

[INFO             ] [MyW         ] This is an info message

The next line also performs a log notation:

 Logger.debug('MyW: This is a debug message.')

This line will produce a debug log commonly used to debug the code. Consider the following line:

   Logger.exception('Something happened!')

This will perform an error log, which would look like:

[ERROR             ] Something happened!

In addition to the three present in this recipe, you can use trace, warning, and critical logging objects.

There’s more…

We also have the trace, warning, error, and critical methods in the Logger class that work similarly to the methods described in this recipe.

The log file by default is located in the .kivy/logs/ folder of the user running the app, but you can always change it in the Kivy configuration file.

Additionally, you can access the last 100 messages for debugging purposes even if the logger is not enabled. This is made with the help of LoggerHistory as follows:

from kivy.logger import LoggerHistory
print(LoggerHistory.history)

So, the console will display the last 100 logs.

See also

More information about logging can be found at http://kivy.org/docs/api-kivy.logger.html.

Parsing

Actually, Kivy has the parser package that helps in the CSS parsing. Even though it is not a complete parsing, it helps to parse instructions related to a framework. The recipe will show some that you could find useful in your context.

How to do it…

The parser package has eight classes, so we will work in Python to review all of them. Let’s follow the next steps:

  1. Import the parser package.
    from kivy.parser import *
  2. Parse a color from a string.
    parse_color('#090909')
  3. Parse a string to a string.
    parse_string("(a,1,2)")a
  4. Parse a string to a boolean value.
    parse_bool("0")
  5. Parse a string to a list of two integers.
    parse_int2("12 54")
  6. Parse a string to a list of four floats.
    parse_float4('54 87.13 35 0.9')
  7. Parse a file name.
    parse_filename('e7.py')

Finally, we have parse_int and parse_float, which are aliases of int and float, respectively.

How it works…

In the second step, we parse any of the common ways to define a color (that is, RGB(r, g, b), RGBA(r, g, b, a), aaa, rrggbb, #aaa or #rrggbb) to a Kivy color definition.

The third step takes off the single or double quotes of the string. The fourth step takes a string True for 1 and False for 0 and parses it to its respective boolean value.

The last step is probably very useful because it permits verification if that file name is a file available to be used. If the file is found, the resource path is returned.

See also

To use a more general parser, you can use ply package for Python. Visit https://pypi.python.org/pypi/ply for further information.

Applying utils

There are some methods in Kivy that cannot be arranged in any other class. They are miscellaneous and could be helpful in some contexts. In this recipe, we will see how to use them.

How to do it…

In the spirit to show all the methods available, let’s work directly in Python. To do the package tour, follow these steps:

  1. Import the kivy package.
    from kivy.utils import *
  2. Find the intersection between two lists.
    intersection(('a',1,2), (1,2))
  3. Find the difference between two lists.
    difference(('a',1,2), (1,2))
  4. Convert a tuple in a string.
    strtotuple("1,2")
  5. Transform a hex string color to a Kivy color.
    get_color_from_hex('#000000')
  6. Transform a Kivy color to a hex value.
    get_hex_from_color((0, 1, 0))
  7. Get a random color.
    get_random_color(alpha='random')
  8. Evaluate if a color is transparent.
    is_color_transparent((0,0,0,0))
  9. Limit the value between a minimum value and maximum value.
    boundary(a,1,2)
  10. Interpolate between two values.
    interpolate(10, 50, step=10)
  11. Mark a function as deprecated.
    deprecated(MyW)
  12. Get the platform where the app is running.
    <p>platform()</p>

How it works…

Almost every method presented in this recipe has a transparent syntax. Let’s get some detail on two of the steps. The ninth step is the boundary method. It evaluates the value of a, and if this is between 1 and 2, it conserves its value; if it is lower than 1, the method returns 1; if it is greater than 2, the method returns 2.

The eleventh step is associated with the warning by using the function MyW; when this function is called the first time, the warning will be triggered.

See also

If you want to explore this package in detail, you can visit http://kivy.org/docs/api-kivy.utils.html.

Leveraging the factory object

The factory object represents the last step to create our own widgets because the factory can be used to automatically register any class or module and instantiate classes from any place in the app. This is a Kivy implementation of the factory pattern where a factory is an object to create other objects. This also opens a lot of possibilities to create dynamic codes in Kivy. In this recipe, we will register one of our widgets.

Getting ready

We will use an adaptation of the code to register the widget as a factory object. Copy the file in the same location of this recipe with the name e7.py.

How to do it…

In this recipe, we will use one of our simple Python files where we will register our widget using the factory package. Follow these steps:

  1. Import the usual kivy packages.
  2. In addition, import the Factory package.
  3. Register the MyWidget
  4. In the build() method of the usual e8App, return Factory.MyWidget.
    import kivy
    kivy.require('1.9.0')
    
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.factory import Factory
    
    Factory.register('MyWidget', module='e7')
    
    classMyW(Widget):
       pass
    
    class e8App(App):
    
       def build(self):
           returnFactory.MyWidget()
    
    if __name__ == '__main__':
       e8App().run()

How it works…

Let us note how the magic is done in the following line:

Factory.register('MyWidget', module='e7')

This line creates the factory object named MyWidget, and let’s use it as we want. See how e7 is the name of the file. Actually, this sentence also will create a file named e7.pyc, which we can use as a replacement of the file e7.py if want to distribute our code; now it is not necessary to give the e7.py, since just the e7.pyc file is enough.

There’s more…

This registration is actually permanent, so if you wish to change the registration in the same code, you need to unregister the object. For example, see the following:

Factory.unregister('MyWidget')
Factory.register('MyWidget', cls=CustomWidget)
New_widget = Factory.MyWidget()

 

See also

If you want to know more about this amazing package, you can visit http://kivy.org/docs/api-kivy.factory.html.

Working with audio

Nowadays, the audio integration in our app is vital. You could not realize a video game without audio or an app that does not use multimedia. We will create a sample with just one button which when pressed plays an audio.

Getting ready

We need an audio file in this recipe in the traditional audio formats (mp3, mp4, wav, wma, b-mtp, ogg, spx, midi). If you do not have any, you always can get one from sites such as https://www.freesound.org.

How to do it…

We will use a simple Python file with just one widget to play the audio file. To complete the recipe, let’s follow these steps:

  1. Import the usual kivy package.
  2. Import the SoundLoader package.
  3. Define the MyW() class.
  4. Define the __init__() method.
  5. Create a button with the label Play.
  6. Bind the press action with the press() method.
  7. Add the widget to the app.
  8. Define the press() method.
  9. Call the SoundLoader.sound() method for your audio file.
  10. Play it with the play()method:
    import kivy
    kivy.require('1.9.0')
    
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.uix.button import Button
    from kivy.core.audio import SoundLoader
    
    class MyW(Widget):
    
       def __init__(self, **kwargs):
           super(MyW, self).__init__(**kwargs)
           b1=Button(text='Play')
           b1.bind(on_press=self.press)
           self.add_widget(b1)
    
       def press(self, instance):
           sound = SoundLoader.load('owl.wav')
           if sound:
               print("Sound found at %s" % sound.source)
               print("Sound is %.3f seconds" % sound.length)
               sound.play()
              print('playing')
    
    class e4App(App):
    
       def build(self):
           returnMyW()
    
    if __name__ == '__main__':
       e4App().run()

How it works…

In this recipe, the audio file is a load in the line:

       sound = SoundLoader.load('owl.wav')

Here, we use a .wav format. Look at the following line:

       if sound:

We handle that the file has been correctly loaded. We have the next line:

  print("Sound found at %s" % sound.source)

This prints the name of the file that has been loaded in the console. The next line prints the duration of the file in seconds. See the other line:

           sound.play()

It is where the file is played in the app.

There’s more…

Also, you can use the seek() and stop() methods to navigate to the audio file. Let’s say that you want to play the audio after the first minute, you will use:

   Sound.seek(60)

The parameter received by the seek() method must be in seconds.

See also

If you need more control of the audio, you should visit http://kivy.org/docs/api-kivy.core.audio.html.

Working with video

The video reproduction is a useful tool for any app. In this app, we will load a widget to reproduce a video file in our app.

Getting ready

It is necessary to have a video file in the usual format to be reproduced in our app (.avi, .mov, .mpg, .mp4, .flv, .wmv, .ogg). If you do not have one, you can visit https://commons.wikimedia.org/wiki/Main_Page to get free media.

How to do it…

In this recipe, we are going to use a simple Python file to create our app within a player widget. To complete the task, follow these:

  1. Import the usual kivy packages.
  2. Import the VideoPlayer package.
  3. Define the MyW() class.
  4. Define the __init__() method.
  5. Define videoplayer with your video.
  6. Add the video player to the app.
    import kivy
    kivy.require('1.9.0')
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.uix.videoplayer import VideoPlayer
    
    class MyW(Widget):
    
       def __init__(self, **kwargs):
           super(MyW, self).__init__(**kwargs)
           player= VideoPlayer(
           source='GOR.MOV',state='play',
           options={'allow_stretch': True},
           size=(600,600))
           self.add_widget(player)
    
    class e5App(App):
    
       def build(self):
           returnMyW()
    
    if __name__ == '__main__':
       e5App().run()

How it works…

In this recipe, the most important line is:

       player= VideoPlayer(
       source='GOR.MOV',state='play',
       options={'allow_stretch': True},
       size=(600,600))

This line loads the file, sets some options, and gives the size to the widget. The option ‘allow stretch’ let’s you modify the image of the video or not. In our recipe, ‘allow stretch’ is permitted, so the images will be maximized to fit in the widget.

There’s more…

You can also integrate subtitles or annotations to the video in an easy way. You only need a JSON-based file with the same name as the video, in the same location with .jsa extension. For example, let’s use this content in the .jsa file:

[
{"start": 0, "duration": 2,

"text": "Here your text"},
{"start": 2, "duration": 2,
"bgcolor": [0.5, 0.2, 0.4, 0.5],

"text": "You can change the background color"}
]

The “start” sentence locates in which second the annotation will show up in the video and the “duration” sentence gives the time in seconds that the annotation will be in the video.

See also

There are some apps that need more control of the video, so you can visit http://kivy.org/docs/api-kivy.core.video.html for better understanding.

Working with a camera

It is very common that almost all our personal devices have a camera. So you could find thousands of ways to use a camera signal in your app. In this recipe, we want to create an app that takes control of the camera present in a device.

Getting ready

Actually, you need to have the correct installation of the packages that permits you to interact with a camera. You can review http://kivy.org/docs/faq.html#gstreamer-compatibility to check if your installation is suitable.

How to do it…

We are going to use the Python and KV files in this recipe. The KV file will deal with the camera and button to interact with it. The Python code is one of our usual Python files with the definition of the root widget. Let’s follow these steps:

  1. In the KV file, define the <MyW> rule.
  2. In the rule, define BoxLayout with a vertical orientation.
  3. Inside the Layout, define the camera widget with play property as false.
  4. Also, define the ToggleButton with the press property swifts between play and
    not play:

    <MyW>:
       BoxLayout:
           orientation: 'vertical'
           Camera:
               id: camera
               play: False
           ToggleButton:
               text: 'Play'
               on_press: camera.play = not camera.play
               size_hint_y: None
               height: '48dp'
  5. In the Python file, import the usual packages.
  6. Define the MyW() class instanced as BoxLayout:
    import kivy
    kivy.require('1.9.0')
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.uix.boxlayout import BoxLayout
    
    class MyW(BoxLayout):
       pass
    
    class e6App(App):
       def build(self):
           return MyW()
    
    if __name__ == '__main__':
       e6App().run()

There’s more…

If we have a device with more than one camera, for example, the handheld device front and rear camera, you can use the index property to switch between them. We have the following line:

id: camera

Add this line in the KV file:

index: 0

The preceding line is to select the first camera, index:1 for the second, and so on.

Using spelling

Depending on the kind of app that we will develop, we will need to spellcheck text provided by the user. In the Kivy API, there is a package to deal with it. In this recipe, we will give an example of how to do it.

Getting ready

If you are not using Mac OS X (or OS X as Apple called now), we will need to install the Python package: PyEnchant. For the installation, let’s use the pip tool as follows:

pip install PyEnchant

How to do it…

Because this recipe could use it in different contexts, let’s work directly in Python. We want to make some suggestions to the word misspelled. To complete the task, follow these steps:

  1. Import the Spelling package.
    from kivy.core.spelling import Spelling
  2. Instance the object s as Spelling().
    s = Spelling()
  3. List the available language.
    s.list_languages()
  4. In this case, select U.S. English.
    s.select_language('en_US')
  5. Ask for a suggestion to the object s.
    s.suggest('mispell')

How it works…

The first four steps actually set the kind of suggestion that we want. The fifth step makes the suggestion in line:

s.suggest('mispell')

The output of the expression is:

[u'misspell', u'ispell']

The output is in the order of the used frequency, so misspell is the most probable word that the user wanted to use.

Adding effects

Effects are one of the most important advances in the computer graphics field. The physics engines help create better effects, and they are under continuous improvement. Effects are pleasing to the end user. They change the whole experience.

The kinetic effect is the mechanism that Kivy uses to approach this technology. This effect can be used in diverse applications from the movement of a button to the simulation of real graphical environments. In this recipe, we will review how to set the effect to use it in our apps.

Getting ready

We are going to use some concepts from physics in this recipe, so it’s necessary to have the clear basics.

You should start reading about this on Wikipedia at http://en.wikipedia.org/wiki/Acceleration.

How to do it…

As the applications of this effect are as creative as you want, we are going to work directly in Python to set up the effect. Let’s follow these steps:

  1. Import the KineticEffect package.
    from kivy.effects.kinetic import KineticEffect
  2. Instance the object effect as KineticEffect().
    effect = KineticEffect()
  3. Start the effect at second 10.
    effect.start(10)
  4. Update the effect at second 15.
    effect.update(15)
  5. Update the effect again at second 30.
    effect.update(30)
  6. You can always add friction to the movement.
    effect.friction
  7. You can also update the velocity.
    effect.update_velocity(30)
  8. Stop the effect at second 48.
    effect.stop(48)
  9. Get the final velocity.
    effect.velocity()
  10. Get the value in seconds.
    effect.value()

How it works…

What we are looking for in this recipe is step 9:

effect.velocity()

The final velocity is how we can use to describe the movement of any object in a realistic way. As the distances are relatively fixed in the app, you need the velocity to describe any motion. We could incrementally repeat the steps to vary the velocity.

There’s more…

There are other three effects based on the Kinetic effect, which are:

  • ScrollEffect: This is the base class used to implement an effect. It only calculates scrolling and overscroll.
  • DampedScrollEffect: This uses the overscroll information to allow the user to drag more than is expected. Once the user stops the drag, the position is returned to one of the bounds.
  • OpacityScrollEffect: This uses the overscroll information to reduce the opacity of the ScrollView widget. When the user stops the drag, the opacity is set back to 1.

See also

If you want to go deeper in this topic, you should visit: http://kivy.org/docs/api-kivy.effects.html.

Advanced text manipulation

Text is one of the most commonly used contents used in the apps. The recipe will create an app with a label widget where we will use text rendering to make our Hello World.

How to do it…

We are going to use one simple Python files that will just show our Hello World text. To complete the recipe:

  1. Import the usual kivy packages.
  2. Also, import the label package.
  3. Define the e9app class instanced as app.
  4. Define the method build() to the class.
  5. Return the label widget with our Hello World text.
    import kivy
    kivy.require('1.9.0') # Code tested in this version!
    from kivy.app import App
    from kivy.uix.label import Label
    
    class e9App(App):
    
       def build(self):
           return Label(text='Hello
           [ref=world][color=0000ff]World[/color][/ref]',
           markup=True, font_size=80, font_name='DroidSans')
    
    if __name__ == '__main__':
       e9App().run()

How it works…

Here is the line:

  return Label(text='Hello
       [ref=world][color=0000ff]World[/color][/ref]', markup=True,
       font_size=80, font_name='DroidSans')

This is the place where the rendering is done. Look at the text parameter where the token [ref] permits us to reference that specific part of the text (for example, to detect a click in the word World) the token [color] gives a particular color to that part of the text. The parameter markup=True allows the use of tokens. The parameters font_size and font_name will let you select the size and font to use for the text.

There’s more…

There are others parameter with evident functions that the label widget can receive like:

  • bold=False
  • italic=False
  • halign=left
  • valign=bottom
  • shorten=False
  • text_size=None
  • color=None
  • line_height=1.0

Here, they have been evaluated with their default values.

See also

If you are interested in creating even more varieties of texts, you can visit http://kivy.org/docs/api-kivy.uix.label.html#kivy.uix.label.Labelor http://kivy.org/docs/api-kivy.core.text.html.

Summary

In this article we learned many things to change the API of our app. We learned to manage images of asynchronous data, to add different effects and to deal with the text visible on the screen. We used audio, video data and camera to create our app. We understood some concept such as exception handling, use of factory objects and parsing of data.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here