Module src.font

Expand source code
from flask_restful import Resource
from werkzeug.utils import secure_filename
import globals
import os
from src import auth
from fontTools import ttLib
from contextlib import redirect_stderr
from webargs.flaskparser import use_kwargs, parser, abort
from webargs import fields
from bson import json_util, ObjectId
import json

fontsDB = globals.fontsDB

auth_args = {"Authorization": fields.Str(required=True)}


def font_name(font_path):
    """
    It takes a font file path as an argument, opens the font file, reads the name table, and returns the
    font name.

    :param font_path: The path to the font file
    :return: The name of the font.
    """

    font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
    with redirect_stderr(None):
        names = font['name'].names

    details = {}
    for x in names:
        if x.langID == 0 or x.langID == 1033:
            try:
                details[x.nameID] = x.toUnicode()
            except UnicodeDecodeError:
                details[x.nameID] = x.string.decode(errors='ignore')

    return details[4]


# class Uploads
# I want to upload a font file and save it to a folder
class FontUpload(Resource):

    # A dictionary that contains a key called fonts. The value of the fonts key is a field object. The
    # field object has a validate method that takes a function as an argument. The function takes a
    # file as an argument and returns a boolean value. The boolean value is true if the file extension
    # is one of the extensions in the list. The field object also has a required method that takes a
    # boolean value as an argument. The boolean value is true if the file is required.
    files_args = {"fonts": fields.Field(validate=lambda file: file.filename.split(
        ".")[-1].lower() in ["ttf", "otf", "woff", "woff2", "eot", "fnt"], required=True)}
    fontName = {"fontname": fields.Str(required=True)}

    # A decorator that is used to validate the files that are being uploaded.
    @use_kwargs(files_args, location="files")
    # A decorator that is used to validate the Authorization header.
    @use_kwargs(auth_args, location="headers")
    # A decorator that is used to validate the fontName argument.
    @use_kwargs(fontName, location="form")
    def post(self, Authorization, fonts, fontname):
        """
        It takes a file, saves it to a temporary folder, checks if the file already exists in the
        database, if it doesn't, it moves the file to the main folder, and then adds it to the database

        :param Authorization: This is the token that is generated when the user logs in
        :param fonts: The file that is being uploaded
        :param fontname: The name of the font you want to use
        :return: The return value is a tuple of the form (response, status, headers)
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            savefonts = []
            filename = secure_filename(fonts.filename)
            tmpFilepath = os.path.join(globals.FONT_FOLDER, "tmp", filename)
            if not os.path.exists(tmpFilepath):
                fonts.save(tmpFilepath)
                fontName = font_name(tmpFilepath)
                existing = fontsDB.find_one({"name": fontName})
                if not existing:
                    filepath = os.path.join(globals.FONT_FOLDER, filename)
                    os.rename(tmpFilepath, filepath)
                    if fontname:
                        inserted_id = str(fontsDB.insert_one(
                            {"name": fontName, "path": filepath, "alias": [fontName, fontname]}).inserted_id)
                        return {"id": inserted_id, "name": fontName, "path": filepath}, 200
                    else:
                        inserted_id = str(fontsDB.insert_one(
                            {"name": fontName, "path": filepath, "alias": [fontName]}).inserted_id)
                        return {"id": inserted_id, "name": fontName, "path": filepath}, 200
                else:
                    return {"msg": "Files Already Exist"}, 201
            else:
                return {"msg": "Files Already Exist"}, 201
        else:
            return "Unauthorized! Access Denied", 401


# It's a class that inherits from the Resource class of the Flask-RESTful library. It has a get method
# that takes in two arguments: Authorization and searchPhase. The Authorization argument is a header
# that is passed in the request. The searchPhase argument is a query parameter that is passed in the
# request. The get method returns a JSON response
class GetFont(Resource):
    # A dictionary that contains a key called searchPhase. The value of the searchPhase key is a field
    # object. The field object has a required method that takes a boolean value as an argument. The
    # boolean value is true if the searchPhase is required.
    search_arg = {"searchPhase": fields.Str(required=True)}

    @use_kwargs(auth_args, location="headers")
    @use_kwargs(search_arg, location="query")
    def get(self, Authorization, searchPhase):
        """
        It searches for a font in the database and returns it if it exists

        :param Authorization: Bearer
        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTg0
        :param searchPhase: the search term
        :return: A list of fonts that match the searchPhase.
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            fonts = list(fontsDB.find({"$or": [
                {'name': {'$regex': searchPhase, "$options": 'i'}},
                {'alias': {'$regex': searchPhase, "$options": 'i'}}
            ]}))
            return json.loads(json_util.dumps(fonts)), 200, {'Access-Control-Allow-Origin': '*'}
        else:
            return "Unauthorized! Access Denied", 401, {'Access-Control-Allow-Origin': '*'}


# This class is used to delete a font from the database
class deleteFont(Resource):
    # A dictionary that contains a key called id. The value of the id key is a field object. The field
    # object has a required method that takes a boolean value as an argument. The boolean value is
    # true if the id is required.
    search_arg = {"id": fields.Str(required=True)}

    # A decorator that is used to validate the Authorization header.
    @use_kwargs(auth_args, location="headers")
    # A decorator that is used to validate the searchPhase argument.
    @use_kwargs(search_arg, location="query")
    def delete(self, Authorization, id):
        """
        It deletes a font from the database

        :param Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzUwMzUwMjIsIm5iZ
        :param id: The id of the font to be deleted
        :return: The response is a JSON object with the following properties:
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            fonts = fontsDB.delete_one({"_id": ObjectId(id)})
            return json.loads(json_util.dumps(fonts)), 200
        else:
            return "Unauthorized! Access Denied", 401

# This error handler is necessary for usage with Flask-RESTful


@parser.error_handler
def handle_request_parsing_error(err, req, schema, *, error_status_code, error_headers):
    """webargs error handler that uses Flask-RESTful's abort function to return
    a JSON error response to the client.
    """
    if not error_status_code:
        abort(400, errors=err.messages)
    else:
        abort(error_status_code, errors=err.messages)

Functions

def font_name(font_path)

It takes a font file path as an argument, opens the font file, reads the name table, and returns the font name.

:param font_path: The path to the font file :return: The name of the font.

Expand source code
def font_name(font_path):
    """
    It takes a font file path as an argument, opens the font file, reads the name table, and returns the
    font name.

    :param font_path: The path to the font file
    :return: The name of the font.
    """

    font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
    with redirect_stderr(None):
        names = font['name'].names

    details = {}
    for x in names:
        if x.langID == 0 or x.langID == 1033:
            try:
                details[x.nameID] = x.toUnicode()
            except UnicodeDecodeError:
                details[x.nameID] = x.string.decode(errors='ignore')

    return details[4]
def handle_request_parsing_error(err, req, schema, *, error_status_code, error_headers)

webargs error handler that uses Flask-RESTful's abort function to return a JSON error response to the client.

Expand source code
@parser.error_handler
def handle_request_parsing_error(err, req, schema, *, error_status_code, error_headers):
    """webargs error handler that uses Flask-RESTful's abort function to return
    a JSON error response to the client.
    """
    if not error_status_code:
        abort(400, errors=err.messages)
    else:
        abort(error_status_code, errors=err.messages)

Classes

class FontUpload

Represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise the appropriate method is called and passed all arguments from the url rule used when adding the resource to an Api instance. See :meth:~flask_restful.Api.add_resource for details.

Expand source code
class FontUpload(Resource):

    # A dictionary that contains a key called fonts. The value of the fonts key is a field object. The
    # field object has a validate method that takes a function as an argument. The function takes a
    # file as an argument and returns a boolean value. The boolean value is true if the file extension
    # is one of the extensions in the list. The field object also has a required method that takes a
    # boolean value as an argument. The boolean value is true if the file is required.
    files_args = {"fonts": fields.Field(validate=lambda file: file.filename.split(
        ".")[-1].lower() in ["ttf", "otf", "woff", "woff2", "eot", "fnt"], required=True)}
    fontName = {"fontname": fields.Str(required=True)}

    # A decorator that is used to validate the files that are being uploaded.
    @use_kwargs(files_args, location="files")
    # A decorator that is used to validate the Authorization header.
    @use_kwargs(auth_args, location="headers")
    # A decorator that is used to validate the fontName argument.
    @use_kwargs(fontName, location="form")
    def post(self, Authorization, fonts, fontname):
        """
        It takes a file, saves it to a temporary folder, checks if the file already exists in the
        database, if it doesn't, it moves the file to the main folder, and then adds it to the database

        :param Authorization: This is the token that is generated when the user logs in
        :param fonts: The file that is being uploaded
        :param fontname: The name of the font you want to use
        :return: The return value is a tuple of the form (response, status, headers)
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            savefonts = []
            filename = secure_filename(fonts.filename)
            tmpFilepath = os.path.join(globals.FONT_FOLDER, "tmp", filename)
            if not os.path.exists(tmpFilepath):
                fonts.save(tmpFilepath)
                fontName = font_name(tmpFilepath)
                existing = fontsDB.find_one({"name": fontName})
                if not existing:
                    filepath = os.path.join(globals.FONT_FOLDER, filename)
                    os.rename(tmpFilepath, filepath)
                    if fontname:
                        inserted_id = str(fontsDB.insert_one(
                            {"name": fontName, "path": filepath, "alias": [fontName, fontname]}).inserted_id)
                        return {"id": inserted_id, "name": fontName, "path": filepath}, 200
                    else:
                        inserted_id = str(fontsDB.insert_one(
                            {"name": fontName, "path": filepath, "alias": [fontName]}).inserted_id)
                        return {"id": inserted_id, "name": fontName, "path": filepath}, 200
                else:
                    return {"msg": "Files Already Exist"}, 201
            else:
                return {"msg": "Files Already Exist"}, 201
        else:
            return "Unauthorized! Access Denied", 401

Ancestors

  • flask_restful.Resource
  • flask.views.MethodView
  • flask.views.View

Class variables

var files_args
var fontName
var methods : Optional[List[str]]

Methods

def post(self, Authorization, fonts, fontname)

It takes a file, saves it to a temporary folder, checks if the file already exists in the database, if it doesn't, it moves the file to the main folder, and then adds it to the database

:param Authorization: This is the token that is generated when the user logs in :param fonts: The file that is being uploaded :param fontname: The name of the font you want to use :return: The return value is a tuple of the form (response, status, headers)

Expand source code
@use_kwargs(files_args, location="files")
# A decorator that is used to validate the Authorization header.
@use_kwargs(auth_args, location="headers")
# A decorator that is used to validate the fontName argument.
@use_kwargs(fontName, location="form")
def post(self, Authorization, fonts, fontname):
    """
    It takes a file, saves it to a temporary folder, checks if the file already exists in the
    database, if it doesn't, it moves the file to the main folder, and then adds it to the database

    :param Authorization: This is the token that is generated when the user logs in
    :param fonts: The file that is being uploaded
    :param fontname: The name of the font you want to use
    :return: The return value is a tuple of the form (response, status, headers)
    """
    if auth.verify(str(Authorization).split(" ")[1]):
        savefonts = []
        filename = secure_filename(fonts.filename)
        tmpFilepath = os.path.join(globals.FONT_FOLDER, "tmp", filename)
        if not os.path.exists(tmpFilepath):
            fonts.save(tmpFilepath)
            fontName = font_name(tmpFilepath)
            existing = fontsDB.find_one({"name": fontName})
            if not existing:
                filepath = os.path.join(globals.FONT_FOLDER, filename)
                os.rename(tmpFilepath, filepath)
                if fontname:
                    inserted_id = str(fontsDB.insert_one(
                        {"name": fontName, "path": filepath, "alias": [fontName, fontname]}).inserted_id)
                    return {"id": inserted_id, "name": fontName, "path": filepath}, 200
                else:
                    inserted_id = str(fontsDB.insert_one(
                        {"name": fontName, "path": filepath, "alias": [fontName]}).inserted_id)
                    return {"id": inserted_id, "name": fontName, "path": filepath}, 200
            else:
                return {"msg": "Files Already Exist"}, 201
        else:
            return {"msg": "Files Already Exist"}, 201
    else:
        return "Unauthorized! Access Denied", 401
class GetFont

Represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise the appropriate method is called and passed all arguments from the url rule used when adding the resource to an Api instance. See :meth:~flask_restful.Api.add_resource for details.

Expand source code
class GetFont(Resource):
    # A dictionary that contains a key called searchPhase. The value of the searchPhase key is a field
    # object. The field object has a required method that takes a boolean value as an argument. The
    # boolean value is true if the searchPhase is required.
    search_arg = {"searchPhase": fields.Str(required=True)}

    @use_kwargs(auth_args, location="headers")
    @use_kwargs(search_arg, location="query")
    def get(self, Authorization, searchPhase):
        """
        It searches for a font in the database and returns it if it exists

        :param Authorization: Bearer
        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTg0
        :param searchPhase: the search term
        :return: A list of fonts that match the searchPhase.
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            fonts = list(fontsDB.find({"$or": [
                {'name': {'$regex': searchPhase, "$options": 'i'}},
                {'alias': {'$regex': searchPhase, "$options": 'i'}}
            ]}))
            return json.loads(json_util.dumps(fonts)), 200, {'Access-Control-Allow-Origin': '*'}
        else:
            return "Unauthorized! Access Denied", 401, {'Access-Control-Allow-Origin': '*'}

Ancestors

  • flask_restful.Resource
  • flask.views.MethodView
  • flask.views.View

Class variables

var methods : Optional[List[str]]
var search_arg

Methods

def get(self, Authorization, searchPhase)

It searches for a font in the database and returns it if it exists

:param Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTg0 :param searchPhase: the search term :return: A list of fonts that match the searchPhase.

Expand source code
@use_kwargs(auth_args, location="headers")
@use_kwargs(search_arg, location="query")
def get(self, Authorization, searchPhase):
    """
    It searches for a font in the database and returns it if it exists

    :param Authorization: Bearer
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTg0
    :param searchPhase: the search term
    :return: A list of fonts that match the searchPhase.
    """
    if auth.verify(str(Authorization).split(" ")[1]):
        fonts = list(fontsDB.find({"$or": [
            {'name': {'$regex': searchPhase, "$options": 'i'}},
            {'alias': {'$regex': searchPhase, "$options": 'i'}}
        ]}))
        return json.loads(json_util.dumps(fonts)), 200, {'Access-Control-Allow-Origin': '*'}
    else:
        return "Unauthorized! Access Denied", 401, {'Access-Control-Allow-Origin': '*'}
class deleteFont

Represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise the appropriate method is called and passed all arguments from the url rule used when adding the resource to an Api instance. See :meth:~flask_restful.Api.add_resource for details.

Expand source code
class deleteFont(Resource):
    # A dictionary that contains a key called id. The value of the id key is a field object. The field
    # object has a required method that takes a boolean value as an argument. The boolean value is
    # true if the id is required.
    search_arg = {"id": fields.Str(required=True)}

    # A decorator that is used to validate the Authorization header.
    @use_kwargs(auth_args, location="headers")
    # A decorator that is used to validate the searchPhase argument.
    @use_kwargs(search_arg, location="query")
    def delete(self, Authorization, id):
        """
        It deletes a font from the database

        :param Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzUwMzUwMjIsIm5iZ
        :param id: The id of the font to be deleted
        :return: The response is a JSON object with the following properties:
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            fonts = fontsDB.delete_one({"_id": ObjectId(id)})
            return json.loads(json_util.dumps(fonts)), 200
        else:
            return "Unauthorized! Access Denied", 401

Ancestors

  • flask_restful.Resource
  • flask.views.MethodView
  • flask.views.View

Class variables

var methods : Optional[List[str]]
var search_arg

Methods

def delete(self, Authorization, id)

It deletes a font from the database

:param Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzUwMzUwMjIsIm5iZ :param id: The id of the font to be deleted :return: The response is a JSON object with the following properties:

Expand source code
@use_kwargs(auth_args, location="headers")
# A decorator that is used to validate the searchPhase argument.
@use_kwargs(search_arg, location="query")
def delete(self, Authorization, id):
    """
    It deletes a font from the database

    :param Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NzUwMzUwMjIsIm5iZ
    :param id: The id of the font to be deleted
    :return: The response is a JSON object with the following properties:
    """
    if auth.verify(str(Authorization).split(" ")[1]):
        fonts = fontsDB.delete_one({"_id": ObjectId(id)})
        return json.loads(json_util.dumps(fonts)), 200
    else:
        return "Unauthorized! Access Denied", 401