Skip to content

Commit

Permalink
Merge pull request #85 from theletterd/python3
Browse files Browse the repository at this point in the history
Python 3 support!
  • Loading branch information
theletterd authored Jul 10, 2024
2 parents f9f1c47 + 86bc3bd commit 9c5ffe9
Show file tree
Hide file tree
Showing 122 changed files with 1,103 additions and 1,214 deletions.
13 changes: 13 additions & 0 deletions .gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
google_appengine
virtualenv_
lib
.tox
env
.git
tmp
loveapp/config-example.py
YelpLove.egg-info
*.pyc
tests/
testing/
.pytest_cache
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ tmp
import/*.csv
import/*.json
venv
env
.vscode
12 changes: 9 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks.git
sha: v0.7.1
rev: v0.7.1
hooks:
- id: autopep8-wrapper
- id: check-added-large-files
Expand All @@ -15,15 +16,20 @@
- id: double-quote-string-fixer
- id: end-of-file-fixer
- id: flake8
language_version: python2.7
language_version: python3.11
- id: fix-encoding-pragma
- id: name-tests-test
- id: pretty-format-json
args: ['--autofix']
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.12.0
hooks:
- id: reorder-python-imports

- repo: https://github.com/Yelp/detect-secrets
sha: 0.9.1
rev: 0.9.1
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: python
python:
- "2.7"
- "3.11"
# command to install dependencies
install: "pip install tox"
# command to run tests
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ To get an idea what Yelp Love looks like go and check out the [screenshots](/scr

Yelp Love runs on [Google App Engine](https://appengine.google.com/).
In order to install Yelp Love you will need a Google account and the
[Google App Engine SDK for Python 2.7](https://cloud.google.com/appengine/docs/standard/python/download).
[Google App Engine SDK for Python](https://cloud.google.com/appengine/docs/standard/python/download).

### Create a new project

Expand Down Expand Up @@ -78,23 +78,23 @@ fields Yelp Love requires for an employee.
The S3 bucket name must be configured in config.py.

In order to access the S3 bucket you have to save AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
using the [Secret](models/secret.py) model. Locally you can open up the
[interactive console](http://localhost:8000/console) and execute the following code:
using the [Secret](models/secret.py) model. Locally, you can temporarily add an endpoint inside loveapp/views/web.py and then navigate to it in your browser (e.g., http://localhost:8080/create_secrets):

```python
from models import Secret

Secret(id='AWS_ACCESS_KEY_ID', value='change-me').put()
Secret(id='AWS_SECRET_ACCESS_KEY', value='change-me').put()
@web_app.route('/create_secrets')
def create_secrets():
from loveapp.models import Secret
Secret(id='AWS_ACCESS_KEY_ID', value='change-me').put()
Secret(id='AWS_SECRET_ACCESS_KEY', value='change-me').put()
return "please delete me now"
```

In production you can either use the [Datastore UI](https://console.cloud.google.com/datastore/entities/)
or the [Remote API](https://cloud.google.com/appengine/docs/python/tools/remoteapi).
In production you can use the [Datastore UI](https://console.cloud.google.com/datastore/entities/).

To kick off the final import you have to run:

```python
from logic import employee
from loveapp.logic import employee
employee.load_employees()
```

Expand Down
48 changes: 2 additions & 46 deletions app.yaml
Original file line number Diff line number Diff line change
@@ -1,56 +1,12 @@
service: default
runtime: python27
api_version: 1
threadsafe: true
runtime: python311
app_engine_apis: true

handlers:
- url: /api/.*
script: main.app
secure: always
- url: /keys/?.*
script: main.app
login: admin
secure: always
- url: /subscriptions/?.*
script: main.app
login: admin
secure: always
- url: /aliases/?.*
script: main.app
login: admin
secure: always
- url: /robots.txt
static_files: static/robots.txt
upload: static/robots.txt
secure: optional
- url: /static
static_dir: static
secure: always
- url: /_themes/(.*)/img/(.*)
static_files: themes/\1/static/img/\2
upload: themes/(.*)/static/img/(.*)
secure: always
login: optional
- url: .* # Anything not explicitly listed above
script: main.app
login: required
secure: always

builtins:
- remote_api: on

libraries:
- name: ssl
version: latest

skip_files:
- ^(.*/)?#.*#$
- ^(.*/)?.*/RCS/.*$
- ^(.*/)?.*\.py[co]$
- ^(.*/)?.*~$
- ^(.*/)?\..*$
- ^YelpLove.egg-info(/.*)?$
- ^config-example.py$
- ^google_appengine(/.*)?$
- ^tmp(/.*)?$
- ^virtualenv_.*$
9 changes: 0 additions & 9 deletions appengine_config.py

This file was deleted.

3 changes: 0 additions & 3 deletions import/employees.csv.example

This file was deleted.

49 changes: 49 additions & 0 deletions loveapp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
import flask_themes2
from flask import Blueprint
from flask import current_app
from flask import Flask
from flask_themes2 import Themes
from flask_themes2 import ThemeTemplateLoader
from google.appengine.api import wrap_wsgi_app

import loveapp.config as config
from loveapp import views
from loveapp.util.auth import is_admin
from loveapp.util.company_values import linkify_company_values
from loveapp.util.converter import RegexConverter
from loveapp.util.csrf import generate_csrf_token


def create_app(theme_loaders=()):
if current_app:
return current_app
app = Flask(__name__.split('.')[0])
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)

app.secret_key = config.SECRET_KEY
app.url_map.converters['regex'] = RegexConverter
app.jinja_env.globals['config'] = config
app.jinja_env.globals['csrf_token'] = generate_csrf_token
app.jinja_env.globals['is_admin'] = is_admin
app.jinja_env.filters['linkify_company_values'] = linkify_company_values

app.register_blueprint(views.web.web_app)
app.register_blueprint(views.api.api_app)
app.register_blueprint(views.tasks.tasks_app)

# flask_themes2 is storing themes_blueprint at the global level
# https://github.com/sysr-q/flask-themes2/blob/master/flask_themes2/__init__.py#L280C1-L281C58
# which means on some parametrized test runs, we run into errors re-adding urls on the blueprint.
# Forcing the reset of themes_blueprint here seems to work
flask_themes2.themes_blueprint = Blueprint('_themes', __name__)
flask_themes2.themes_blueprint.jinja_loader = ThemeTemplateLoader(True)
Themes(app, app_identifier='yelplove', loaders=theme_loaders)

# if debug property is present, let's use it
try:
app.debug = config.DEBUG
except AttributeError:
app.debug = False

return app
File renamed without changes.
4 changes: 4 additions & 0 deletions loveapp/import/employees.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
username,first_name,last_name,office,department,photo_url
duncan,Duncan,Cook,Awesomeness Office,Department Of Awesome,https://placehold.it/100x100
hbomb,Harrison,Cook,,,https://placehold.it/100x100
niffs,Jennifer,Cook,,,https://placehold.it/100x100
3 changes: 3 additions & 0 deletions loveapp/import/employees.csv.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
username,first_name,last_name,department,office,photo_url
john,John,Doe,,,https://placehold.it/100x100
janet,Janet,Doe,,,https://placehold.it/100x100
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
"first_name": "John",
"last_name": "Doe",
"department": "",
"office": "",
"photo_url": "https://placehold.it/100x100"
},
{
"username": "janet",
"first_name": "Janet",
"last_name": "Doe",
"department": "",
"office": "",
"photo_url": "https://placehold.it/100x100"
}
]
6 changes: 3 additions & 3 deletions logic/__init__.py → loveapp/logic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from datetime import timedelta
from itertools import izip_longest
from itertools import zip_longest

import pytz
from google.appengine.ext import ndb
Expand All @@ -13,11 +13,11 @@
def chunk(iterable, chunk_size):
"""Collect data into fixed-length chunks or blocks (http://docs.python.org/2/library/itertools.html#recipes)"""
args = [iter(iterable)] * chunk_size
return izip_longest(*args)
return zip_longest(*args)


def to_the_future(dict):
for k, v in dict.iteritems():
for k, v in dict.items():
if issubclass(v.__class__, ndb.Future):
dict[k] = v.get_result()

Expand Down
5 changes: 2 additions & 3 deletions logic/alias.py → loveapp/logic/alias.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-

from models import Alias
from models import Employee
from loveapp.models import Alias
from loveapp.models import Employee


def get_alias(alias):
Expand Down
3 changes: 1 addition & 2 deletions logic/department.py → loveapp/logic/department.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-

from models.employee import Employee
from loveapp.models.employee import Employee


def get_all_departments():
Expand Down
8 changes: 4 additions & 4 deletions logic/email.py → loveapp/logic/email.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from google.appengine.api.mail import EmailMessage

from util.email import get_name_and_email
import config
import logic.secret
import loveapp.config as config
import loveapp.logic.secret
from loveapp.util.email import get_name_and_email

if config.EMAIL_BACKEND == 'sendgrid':
# a bit of a hack here so that we can avoid adding dependencies unless
Expand All @@ -22,7 +22,7 @@ def send_appengine_email(sender, recipient, subject, body_html, body_text):


def send_sendgrid_email(sender, recipient, subject, body_html, body_text):
key = logic.secret.get_secret('SENDGRID_API_KEY')
key = loveapp.logic.secret.get_secret('SENDGRID_API_KEY')
sg = sendgrid.SendGridAPIClient(apikey=key)

from_ = sendgrid.helpers.mail.Email(*get_name_and_email(sender))
Expand Down
Loading

0 comments on commit 9c5ffe9

Please sign in to comment.