{"id":19600621,"url":"https://github.com/stanwood/gae-webapp2-utils","last_synced_at":"2025-06-20T13:34:35.655Z","repository":{"id":92390505,"uuid":"143006145","full_name":"stanwood/gae-webapp2-utils","owner":"stanwood","description":"Set of utilities modules for webapp2 framework on GAE: http://webapp2.readthedocs.io/en/latest/","archived":false,"fork":false,"pushed_at":"2018-08-01T07:14:15.000Z","size":23,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-02-26T15:34:20.321Z","etag":null,"topics":["google-app-engine","pytest","python27","webapp2"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stanwood.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-31T11:38:10.000Z","updated_at":"2018-10-12T16:10:42.000Z","dependencies_parsed_at":"2023-05-17T02:30:18.605Z","dependency_job_id":null,"html_url":"https://github.com/stanwood/gae-webapp2-utils","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/stanwood/gae-webapp2-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stanwood%2Fgae-webapp2-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stanwood%2Fgae-webapp2-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stanwood%2Fgae-webapp2-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stanwood%2Fgae-webapp2-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stanwood","download_url":"https://codeload.github.com/stanwood/gae-webapp2-utils/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stanwood%2Fgae-webapp2-utils/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260953476,"owners_count":23088046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-app-engine","pytest","python27","webapp2"],"created_at":"2024-11-11T09:15:40.499Z","updated_at":"2025-06-20T13:34:30.644Z","avatar_url":"https://github.com/stanwood.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GAE Webapp2 utils\n\n## About\n\nHelper module for most common features used in webapp2 and Google App Engine.\n\n## Install\n\nAdd folder as a git submodule:\n```\ngit submodule add git:...\n```\n\nAdd submodule folder to the `appengine_config.py`:\n```python\nimport os\n\nfrom google.appengine.ext import vendor\n\nvendor.add(os.path.join(os.path.dirname(__file__), 'path/to/submodule/webapp2_utils'))\n```\n\n## Usage\n\n### Handlers\n\nCreate simple webapp2 handler which returns JSON body with CORS and Public Cache\n\n```python\nfrom webapp2_utils.handlers import base\nfrom webapp2_utils.handlers.mixins import cache\nfrom webapp2_utils.handlers.mixins import cors\n\n\nclass SampleHandler(base.BaseHandler, cors.HandlerMixin, cache.PublicCachingMixin):\n    def get(self):\n        self.json_response({'msg': 'My sample response in json'})\n```\n\n--- \n\nCreate simple webapp2 handler which downloads file from Google Cloud Storage\n\n```python\nfrom webapp2_utils.handlers import base\nfrom webapp2_utils.handlers.mixins import gcs\n\n\nclass BlobHandler(base.BaseHandler, gcs.CloudStorageMixin):\n    def get(self):\n        file_name = self.request.GET.get('file_name')\n        blob = self.bucket.get_blob(file_name)\n        if not blob:\n            self.abort(404, 'File does not exist on GCS')\n        \n        self.json_response({'file_url': blob.generate_signed_url()})\n```\n\n---\n\nCreate secured handler with auth token\n\n```python\nfrom webapp2_utils.handlers import base\nfrom webapp2_utils.handlers import decorators\n\nclass SecuredHandler(base.BaseHandler):\n    @decorators.token_required('my-auth-token')\n    def get(self):\n        self.json_response({'msg': 'Success auth'})\n```\n\n---\n\nCreate internationalized handler\n```python\nfrom webapp2_extras.i18n import gettext as _\n\nfrom webapp2_utils.handlers import base\nfrom webapp2_utils.handlers.mixins import i18n as i18n_mixin\n\n\nclass TranslatedHandler(base.BaseHandler, i18n_mixin.I18nRequestHandler):\n    def get(self):\n        self.json_response({'msg': _('This is my translated text')})\n```\n\n## Pytest\n\nTest webapp2 handler\n```python\nimport pytest\nimport webtest\n\n@pytest.fixture\ndef app(testbed):\n    from main import app\n    return webtest.TestApp(app)\n    \n\nfrom webapp2_utils.pytest.appengine_fixtures import *\n\ndef test_handler(app):\n    \n    response = app.get('/my/url')\n    assert response.status_code == 200\n```\n\nUsing `freezegun` in Google App Engine test config\n\n```python\nimport datetime\n\nimport freezegun\n\nfrom webapp2_utils.handlers import base\n\nclass DateHandler(base.BaseHandler):\n    \"\"\"Routed as /date url\"\"\"\n    def get(self):\n        self.json_response({'date': datetime.datetime.now().date().isoformat()})\n\n\nfrom webapp2_utils.pytest.appengine_fixtures import *  # import it in conftest\n\n@freezegun.freeze_time('2018-08-08')\ndef test_date_handler(app, freezegun_patch):\n    response = app.get('/date')\n    \n    assert response.json['date'] == '2018-08-08'\n```\n\nTesting `taskqueues` in Google App Engine\n\n```python\nimport webapp2\nfrom google.appengine.api import taskqueue\n\nfrom webapp2_utils.handlers import base\n\nclass TaskHandler(base.BaseHandler):\n    @webapp2.cached_property\n    def queue(self):\n        return taskqueue.Queue('sampleTask')\n\n    def get(self):\n        url = '/_ah/queue/sample/task'\n        self.queue.add(taskqueue.Task(url=url))\n\n\nfrom webapp2_utils.pytest.appengine_fixtures import *  # import it in conftest\n\ndef test_task_handler(app, taskqueue):\n    app.get('/task')\n    \n    tasks = taskqueue.GetTasks(queue_name='queueName')\n\n    assert len(tasks) == 1\n    assert tasks[0]['url'] == '/_ah/queue/sample/task'\n```\n\n\n## ndb\n\nCreate base model with created and updated fields\n\n```python\nfrom google.appengine.ext import ndb\n\nfrom webapp2_utils.ndb.models.base import Model\n\n\nclass MyModel(Model):\n    new_field = ndb.StringProperty()\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstanwood%2Fgae-webapp2-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstanwood%2Fgae-webapp2-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstanwood%2Fgae-webapp2-utils/lists"}