Giter Club home page Giter Club logo

hatsunem.icu's Introduction

hatsunem.icu

hatsunem.icu is a flask based web application which fetches a random video from my carefully curated playlist of music featuring the vocaloid hatsune miku. hatsunem.icu is hosted on heroku and served with gunicorn.

hatunsem.icu fetches video information using Google's Youtube API v3 from a public playlist hosted on my own personal Youtube account.

Resources

Deploying a Flask Application using Gunicorn and Heroku

Retreiving all playlist items using nextPageToken attribute - stanzheng

Playlist on Youtube


marie creel - may 2019 - MIT license - [email protected]

hatsunem.icu's People

Stargazers

 avatar

Watchers

 avatar

hatsunem.icu's Issues

General code feedback:

So here is some feedback on the repo, as requested:

All in all, it runs, and is readable, so thats better great. But there are a few improvements I would recommend making. If just to familiarize yourself with these parts of python.

I'll break it into a few things:

House keeping:

I would remove the pycache and DS_Store files from the repo, as those are local references to your system and dont serve any purpose to me other the making me thting its only meant for you to run or you forgot a .gitignore file.

Just nix the ./__pycache__ and ./templates/.DS_Store stuff and make a .gitignore for the repo. Here is a good template to cover most junky files you dont want in a repo: https://github.com/python/mypy/blob/master/.gitignore

I'll mention this in the other repos, but is a problem there too. Their ignore lists will be different though.

Packages:

To the base pip/venv/setup.py stuff is fine, but a lot of python houses like more formal package/env managers (though some really prefer this style of packaging). If you want, I would look into poetry (stay a mile away from pipenv). It will handle most of the root level project files and also give you a .lock file for reproducible builds. Which is nice.

I would also make sure you're using something like pyenv to manage your python versions, cause that helps with this package business.

Idioms:

Comments

The single-file-server is totally fine given the services size, but some of the commenting is a little oddly formatted.
A good rule of thtumb for comments in python are:

def foo(x)
    """ This is for a person interfacing with the code.
    """
    ... # This is for maintainers of the code it is commenting on.

The triple-# thing feels like a racket comment idiom to me. In python, an inline is to describe implementation
details vs a comment block which is to tell people who are using the code how to use it. Your comments bridge both. Also comments should match the indentation of the code thet are commenting to help connect its context.

I would also look into comment style linters.

The comment style just helps keep things consistent. You can use any of the major styles, but I would recommend googles.

But you can automate a lot of these these comment things with stuff like pylint.

Types

Modern python has type annotations! I promise they make your life saner.
They are enforced by an external tool called mypy.

Lets take some un-annotated code:

def make_manifest_from_user(user_record, action=None, allow_empty_fields=True):
    has_empty = len(user_record.values()) == len([val for val in user_record.values() if val ])
    if has_empty and not allow_empty_fields:
        raise RuntimeError(f'Empty values in user_record: {user_record}')
    
    action_requested = action.get('action_requested')
    return {
        'user': user_record,
        'action_requested': action_requested
    }

Now if you needed to use this, you might be able to figure out what args are needed to work,
But some lines are rough. The action_requested = action.get('action_requested') in particular. What is that value?

Lets redo it with annotations:

import typing as T
def make_manifest_from_user(
    user_record: T.Dict[str, T.Any], 
    action: T.Dict[str, str]=None, 
    allow_empty_fields: bool = True
) -> T.Dict[str, T.Union[T.Dict, str]]:
    has_empty: bool = len(user_record.values()) == len([val for val in user_record.values() if val])
    if has_empty and not allow_empty_fields:
        raise RuntimeError(f'Empty values in user_record: {user_record}')
    
    action_requested: str = action.get('action_requested')
    return {
        'user': user_record,
        'action_requested': action_requested
    }

Now thats more complicated looking, but we have type info so there is some heads up about what values code is expected to handle. It also allows mypy to catch type errors in your code, which has saved me a few times.

Actual code suggestions:

This segment of code is a little weird:

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = #<insert developer key here>

That is, I suspect, something you are suppose to set manually before running. Which is fine, I have a lot of code that works that way. But there is also a better pattern: Singletons. Singletons are like objects, but there are only ever one of them.
So they can be used as stores for centralized data. Python doesnt have a lot of good way to handle them, but there are a few.
In particular, the feature dataclasses.

They do most of the singleton work for you (though not all of it). I would recommend using a small wrapper to
help with configuration of code via data classes using this library: https://github.com/sandal-tan/pyenvclasses

Its from a coworker of mine.

It lets you write classes with attributes and, if there isnt a default assigned, if will look in your bash profile for
bash variables using the same name to populate the value.

for example:

$ export my_var='oh, hi!'
$python
Python 3.8.2 (default, Apr 15 2020, 17:12:22)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import typing as T
>>> from envclasses import EnvClassMeta
>>>
>>> class MyEnv(metaclass=EnvClassMeta):
>>>    my_var: str
>>>
>>> ENV = MyEnv()
>>> print(ENV.my_var)

'oh, hi!'

Conclusion

This might feel like a lot of stuff, but its mostly cause I am approaching this as a normal PR from my coworkers.
Its rad, and it works, and thats 90% of what matters.

This is nearly all stuff I learned after I got a job.

If you have any questions, I am more than happy to dig in further.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.