Backend
This commit is contained in:
parent
a03953a0ab
commit
84a1e7d972
71 changed files with 22530 additions and 0 deletions
0
.gitignore → ember-ui/.gitignore
vendored
0
.gitignore → ember-ui/.gitignore
vendored
0
package-lock.json → ember-ui/package-lock.json
generated
0
package-lock.json → ember-ui/package-lock.json
generated
1
python-api/.gitignore
vendored
Normal file
1
python-api/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/__pycache__
|
112
python-api/.ropeproject/config.py
Normal file
112
python-api/.ropeproject/config.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
# The default ``config.py``
|
||||
# flake8: noqa
|
||||
|
||||
|
||||
def set_prefs(prefs):
|
||||
"""This function is called before opening the project"""
|
||||
|
||||
# Specify which files and folders to ignore in the project.
|
||||
# Changes to ignored resources are not added to the history and
|
||||
# VCSs. Also they are not returned in `Project.get_files()`.
|
||||
# Note that ``?`` and ``*`` match all characters but slashes.
|
||||
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
|
||||
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
|
||||
# '.svn': matches 'pkg/.svn' and all of its children
|
||||
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
|
||||
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
|
||||
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
|
||||
'.hg', '.svn', '_svn', '.git', '.tox']
|
||||
|
||||
# Specifies which files should be considered python files. It is
|
||||
# useful when you have scripts inside your project. Only files
|
||||
# ending with ``.py`` are considered to be python files by
|
||||
# default.
|
||||
#prefs['python_files'] = ['*.py']
|
||||
|
||||
# Custom source folders: By default rope searches the project
|
||||
# for finding source folders (folders that should be searched
|
||||
# for finding modules). You can add paths to that list. Note
|
||||
# that rope guesses project source folders correctly most of the
|
||||
# time; use this if you have any problems.
|
||||
# The folders should be relative to project root and use '/' for
|
||||
# separating folders regardless of the platform rope is running on.
|
||||
# 'src/my_source_folder' for instance.
|
||||
#prefs.add('source_folders', 'src')
|
||||
|
||||
# You can extend python path for looking up modules
|
||||
#prefs.add('python_path', '~/python/')
|
||||
|
||||
# Should rope save object information or not.
|
||||
prefs['save_objectdb'] = True
|
||||
prefs['compress_objectdb'] = False
|
||||
|
||||
# If `True`, rope analyzes each module when it is being saved.
|
||||
prefs['automatic_soa'] = True
|
||||
# The depth of calls to follow in static object analysis
|
||||
prefs['soa_followed_calls'] = 0
|
||||
|
||||
# If `False` when running modules or unit tests "dynamic object
|
||||
# analysis" is turned off. This makes them much faster.
|
||||
prefs['perform_doa'] = True
|
||||
|
||||
# Rope can check the validity of its object DB when running.
|
||||
prefs['validate_objectdb'] = True
|
||||
|
||||
# How many undos to hold?
|
||||
prefs['max_history_items'] = 32
|
||||
|
||||
# Shows whether to save history across sessions.
|
||||
prefs['save_history'] = True
|
||||
prefs['compress_history'] = False
|
||||
|
||||
# Set the number spaces used for indenting. According to
|
||||
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
|
||||
# unit-tests use 4 spaces it is more reliable, too.
|
||||
prefs['indent_size'] = 4
|
||||
|
||||
# Builtin and c-extension modules that are allowed to be imported
|
||||
# and inspected by rope.
|
||||
prefs['extension_modules'] = []
|
||||
|
||||
# Add all standard c-extensions to extension_modules list.
|
||||
prefs['import_dynload_stdmods'] = True
|
||||
|
||||
# If `True` modules with syntax errors are considered to be empty.
|
||||
# The default value is `False`; When `False` syntax errors raise
|
||||
# `rope.base.exceptions.ModuleSyntaxError` exception.
|
||||
prefs['ignore_syntax_errors'] = False
|
||||
|
||||
# If `True`, rope ignores unresolvable imports. Otherwise, they
|
||||
# appear in the importing namespace.
|
||||
prefs['ignore_bad_imports'] = False
|
||||
|
||||
# If `True`, rope will insert new module imports as
|
||||
# `from <package> import <module>` by default.
|
||||
prefs['prefer_module_from_imports'] = False
|
||||
|
||||
# If `True`, rope will transform a comma list of imports into
|
||||
# multiple separate import statements when organizing
|
||||
# imports.
|
||||
prefs['split_imports'] = False
|
||||
|
||||
# If `True`, rope will remove all top-level import statements and
|
||||
# reinsert them at the top of the module when making changes.
|
||||
prefs['pull_imports_to_top'] = True
|
||||
|
||||
# If `True`, rope will sort imports alphabetically by module name instead of
|
||||
# alphabetically by import statement, with from imports after normal
|
||||
# imports.
|
||||
prefs['sort_imports_alphabetically'] = False
|
||||
|
||||
# Location of implementation of rope.base.oi.type_hinting.interfaces.ITypeHintingFactory
|
||||
# In general case, you don't have to change this value, unless you're an rope expert.
|
||||
# Change this value to inject you own implementations of interfaces
|
||||
# listed in module rope.base.oi.type_hinting.providers.interfaces
|
||||
# For example, you can add you own providers for Django Models, or disable the search
|
||||
# type-hinting in a class hierarchy, etc.
|
||||
prefs['type_hinting_factory'] = 'rope.base.oi.type_hinting.factory.default_type_hinting_factory'
|
||||
|
||||
|
||||
def project_opened(project):
|
||||
"""This function is called after opening the project"""
|
||||
# Do whatever you like here!
|
BIN
python-api/.ropeproject/globalnames
Normal file
BIN
python-api/.ropeproject/globalnames
Normal file
Binary file not shown.
BIN
python-api/.ropeproject/history
Normal file
BIN
python-api/.ropeproject/history
Normal file
Binary file not shown.
BIN
python-api/.ropeproject/objectdb
Normal file
BIN
python-api/.ropeproject/objectdb
Normal file
Binary file not shown.
13
python-api/README.md
Normal file
13
python-api/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Python Backend for Sortable Recipes (EmberConf 2020)
|
||||
|
||||
## Getting Started
|
||||
|
||||
```bash
|
||||
pip3 install requests gunicorn pycnic
|
||||
gunicorn api:app
|
||||
```
|
||||
|
||||
### Available Endpoints:
|
||||
|
||||
`http://localhost:8000/meals/random`
|
||||
`http://localhost:8000/meal/{meal_id}`
|
BIN
python-api/__pycache__/api.cpython-37.pyc
Normal file
BIN
python-api/__pycache__/api.cpython-37.pyc
Normal file
Binary file not shown.
BIN
python-api/__pycache__/key_replacer.cpython-37.pyc
Normal file
BIN
python-api/__pycache__/key_replacer.cpython-37.pyc
Normal file
Binary file not shown.
71
python-api/api.py
Normal file
71
python-api/api.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
from pycnic.core import WSGI, Handler
|
||||
from key_replacer import KeyReplacer
|
||||
import requests
|
||||
import json
|
||||
|
||||
class Base(Handler):
|
||||
hostname = "https://www.themealdb.com/api/json/v1/1/"
|
||||
|
||||
def __init__(self):
|
||||
self.replacable_keys = KeyReplacer(
|
||||
[
|
||||
["idMeal", "id"],
|
||||
["strMeal", "name"],
|
||||
["strCategory", "category"],
|
||||
["strArea", "area"],
|
||||
["strInstructions", "instructions"],
|
||||
["strDrinkAlternate", "alternate_drink"],
|
||||
["strMealThumb", "thumbnail_url"],
|
||||
["strTags", "tags"],
|
||||
["strYoutube", "youtube_url"],
|
||||
["strSource", "source_url"],
|
||||
["dateModified", "date_modified"],
|
||||
])
|
||||
def cleanup(self, meal):
|
||||
self.replacable_keys.do_replace(meal)
|
||||
self.cleanup_ingredients(meal)
|
||||
|
||||
def cleanup_ingredients(self, meal):
|
||||
potential_length = 20
|
||||
true_length = 0
|
||||
# Cleanup Empty Values
|
||||
for i in reversed(range(potential_length)):
|
||||
x = str(i + 1)
|
||||
if (meal["strIngredient" + x] == ''):
|
||||
true_length = i
|
||||
del meal["strIngredient" + x]
|
||||
del meal["strMeasure" + x]
|
||||
|
||||
# Convert Ingredients/Measures to Array of Objects
|
||||
meal["ingredients"] = [0]*true_length
|
||||
for i in range(0, true_length):
|
||||
x = str(i + 1)
|
||||
meal["ingredients"][i] = {
|
||||
"name": meal["strIngredient" + x],
|
||||
"measure": meal["strMeasure" + x],
|
||||
}
|
||||
del meal["strIngredient" + x]
|
||||
del meal["strMeasure" + x]
|
||||
|
||||
class Details(Base):
|
||||
def get(self, meal_id = ''):
|
||||
response = json.loads(requests.get(self.hostname + "lookup.php?i=" + meal_id).text)
|
||||
for meal in response["meals"]:
|
||||
self.cleanup(meal)
|
||||
|
||||
return json.dumps(response)
|
||||
|
||||
|
||||
class Random(Base):
|
||||
def get(self):
|
||||
response = json.loads(requests.get(self.hostname + "random.php").text)
|
||||
for meal in response["meals"]:
|
||||
self.cleanup(meal)
|
||||
|
||||
return json.dumps(response)
|
||||
|
||||
class app(WSGI):
|
||||
routes = [
|
||||
("/meals/random", Random()),
|
||||
("/meal/([\w]+)", Details())
|
||||
]
|
22318
python-api/get-pip.py
Normal file
22318
python-api/get-pip.py
Normal file
File diff suppressed because it is too large
Load diff
15
python-api/key_replacer.py
Normal file
15
python-api/key_replacer.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
class KeyReplacer():
|
||||
def __init__(self, replacements = []):
|
||||
self.replacements = self._build_replacements(replacements)
|
||||
|
||||
def _build_replacements(self, replacements):
|
||||
return list(map(lambda r: { "old": r[0], "new": r[1] }, replacements))
|
||||
|
||||
def _rename(self, obj, old_key, new_key):
|
||||
obj[new_key] = obj[old_key]
|
||||
del obj[old_key]
|
||||
|
||||
def do_replace(self, obj):
|
||||
for replacement in self.replacements:
|
||||
self._rename(obj, replacement["old"], replacement["new"])
|
||||
|
Loading…
Add table
Reference in a new issue