Yandex.Functions, Sublime Text and skills for Alice

On June 27, Yandex held an online hackathon to develop skills for Alice.



I also decided to take part in it. I have already done skills for Alice, but I hosted them all on Google App Engine. Immediately I decided to learn something new within the Hackathon. Yandex is actively promoting its Functions in Yandex.Cloud for skill development. For skills, they are free (though not everything is free).



And Google App Engine now requires an account to be connected for payment in order to upload the application to the server.



I decided to try the skill in Yandex.Cloud to place. In addition, I decided, the skill should be simple - in order to have time to do it in a day within the Hackathon. Here Functions in the Cloud are very suitable - you do not need to access third-party services (they are paid for in functions), data can be stored in the skill itself , an external database is not needed.



Previously, I tried to do useful skills - to pay for parking by voice, for example (in Yandex.Navigator) or to find out when the bus / trolleybus / tram will arrive at the nearest stop. This required integrations with third-party services, long development, and Yandex, judging by the Alice award, more gaming and entertainment skills to your liking. So this time I decided to make a game.



To work with the Functions, it is proposed to either do everything locally, and then upload the files in the Functions, or edit the files in the online editor. I love online editors;), so first I tried to use it. However, after two or three or four edits and saving new versions, I decided to abandon this idea - it is very inconvenient that clicking on Save will redirect you to another screen. In total, each edit is a bunch of extra clicks.



It's a little easier to live with a command line . But the files need to be added to zip every time, and only then loaded into the Cloud. Hands - uncomfortable.



It just so happened that my IDE is Sublime Text 3. Recently Google abandoned the Google App Engine Launcher and the only option left with it is downloading files via the command line. It was then that I learned about the existence of build systems in Sublime Text - press Ctrl / Cmd + B and Sublime executes the command you need. For GAE, I then made a set of commands , I decided that something similar was needed here.



First, functionality was made to simply download files.



For GAE, I made it so that the passed parameters (namely, the project name) were read from the Sublime Text project file. To save time, the name of the function, the entry point and other parameters are just hardcoded into the build system. Not very good, but suitable for my purposes.







But if everything is tested on a production server, then the logs should be somehow conveniently viewed. Therefore, a separate command was added to load and display logs.



Alas, if the logs are easy to display, then it is quite difficult to navigate in them.



I had to tinker a bit with the command (so that unicode strings were displayed correctly - but even then, this does not always work), with the code itself (to display JSON in a readable form):



    logging.getLogger().setLevel(logging.DEBUG)
    logging.debug('REQUEST: ')
    for line in json.dumps(event['request'], indent=4).split('\n'):
        logging.debug(line)


and create a separate syntax file to highlight errors in the log.







A separate handy feature - Sublime Text is able to highlight the line itself if it found it in the code.



The total is the following -



Yandex Cloud.sublime-build file
// Install Yandex CLI - https://cloud.yandex.ru/docs/cli/quickstart#install
//
// http://www.sublimetext.com/docs/3/build_systems.html
// https://cloud.yandex.ru/docs/functions/operations/function/version-manage#version-create
{
    "file_patterns": ["*.py"],
    "syntax": "Packages/User/YCLog.sublime-syntax",
    "file_regex": "File \\\"/function/code/(...*?)\\\", line ([0-9]*)", 
    "variants":
        [
            {
                "name": "Upload",
                "shell_cmd": "zip -u -0 yc_upload.zip *.py && yc serverless function version create --function-name=my-function-name --runtime=python27 --entrypoint=main.handler --memory=128m --execution-timeout=2s --source-path=yc_upload.zip",
            },
            {
                "name": "Logs",
                "shell_cmd": "printf '%b\n' \"\\$(yc serverless function logs alice-guess-the-language)\""
            }
        ]
}




YCLog.sublime-syntax file
%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
name: YC Log
file_extensions: [log]
scope: source.example-c
contexts:
  main:
    # Request identifiers
    - match: '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (START|END|REPORT) RequestID: .*'
      scope: storage.type.string.c

    # Dates
    - match: '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
      scope: comment.line.c

    - match: '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{2,3}Z    [0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}'
      scope: comment.line.c

    # Log level
    - match: '\[(INFO|DEBUG)\]'
      scope: comment.line.example-c

    # Log level
    - match: '\[(ERROR|WARNING)\]'
      scope: keyword.control.flow.break.c


    # Strings begin and end with quotes, and use backslashes as an escape
    # character
    - match: '"'
      scope: punctuation.definition.string.begin.c
      push: double_quoted_string


  double_quoted_string:
    - meta_scope: string.quoted.double.example-c
    - match: '\\.'
      scope: constant.character.escape.example-c
    - match: '"'
      scope: punctuation.definition.string.end.example-c
      pop: true




It's much nicer to edit the Function code in Yandex.Cloud.



PS My skill is the game Guess the Language .



All Articles