Unified
Split
Showing
with
688 additions
and 332 deletions.
- +9 −0 .hound.yml
- +7 −0 .jshintignore
- +28 −0 .jshintrc
- +2 −9 .prospector.yaml
- +10 −5 .travis.yml
- +17 −0 CHANGES.txt
- +2 −0 Makefile
- +10 −9 README.rst
- +0 −1 conf/development.ini
- +0 −1 conf/production.ini
- +2 −2 docs/hacking/index.rst
- +16 −0 h/accounts/models.py
- +1 −0 h/accounts/test/models_test.py
- +1 −0 h/accounts/test/views_test.py
- +7 −7 h/app.py
- +0 −14 h/assets.py
- +2 −6 h/assets.yaml
- +1 −0 h/claim/test/views_test.py
- +1 −0 h/conftest.py
- +1 −3 h/features.py
- +0 −13 h/renderers.py
- +12 −6 h/static/scripts/app-controller.coffee
- +6 −29 h/static/scripts/app.coffee
- +8 −6 h/static/scripts/config/accounts.coffee
- +0 −24 h/static/scripts/config/features.coffee
- +0 −29 h/static/scripts/directive/repeat-anim.coffee
- +1 −1 h/static/scripts/test/app-controller-test.coffee
- +21 −0 h/static/styles/common.scss
- +3 −3 h/static/styles/help-page.scss
- +2 −3 h/static/styles/simple-search.scss
- +1 −1 h/static/styles/topbar.scss
- BIN h/static/styles/vendor/fonts/h.eot
- +263 −143 h/static/styles/vendor/fonts/selection.json
- +18 −2 h/static/styles/vendor/icomoon.css
- +2 −0 h/subscribers.py
- +20 −5 h/templates/app.html
- +13 −5 h/templates/help.html
- +3 −2 h/test/assets_test.py
- +1 −0 h/test/factories.py
- +1 −0 h/test/factories_test.py
- +1 −0 h/test/models_test.py
- +179 −1 h/test/views_test.py
- +14 −1 h/views.py
- +2 −1 setup.py
| @@ -0,0 +1,9 @@ | ||
| coffeescript: | ||
| enabled: false | ||
| javascript: | ||
| config_file: .jshintrc | ||
| ignore_file: .jshintignore | ||
| ruby: | ||
| enabled: false | ||
| scss: | ||
| enabled: false |
| @@ -0,0 +1,7 @@ | ||
| build/ | ||
| docs/ | ||
| node_modules/ | ||
| h/browser/chrome/content/ | ||
| h/static/scripts/vendor/ | ||
| h/templates/ | ||
| **/*.min.js |
| @@ -0,0 +1,28 @@ | ||
| { | ||
| "bitwise": true, | ||
| "curly": true, | ||
| "eqeqeq": true, | ||
| "forin": true, | ||
| "freeze": true, | ||
| "latedef": "nofunc", | ||
| "maxcomplexity": 10, | ||
| "strict": true, | ||
| "undef": true, | ||
| "unused": true, | ||
| "globals": { | ||
| "chrome": false, | ||
| "h": false, | ||
| "Promise": false, | ||
| "angular": false, | ||
| "chai": false, | ||
| "moment": false, | ||
| "jstz": false, | ||
| "sinon": false, | ||
| "JSON": false | ||
| }, | ||
| "browser": true, | ||
| "browserify": true, | ||
| "mocha": true, | ||
| "phantom": true, | ||
| "jquery": true | ||
| } |
| @@ -9,9 +9,6 @@ pylint: | ||
| enable: | ||
| - relative-import | ||
| disable: | ||
| - C0111 # Missing %s docstring | ||
| - R0201 # Method could be a function | ||
| - W0704 # Except doesn't do anything | ||
| - R0903 # Too few public methods | ||
| - W0142 # Used * or ** magic | ||
| options: | ||
| @@ -35,12 +32,8 @@ pylint: | ||
| # By default PyLint doesn't allow function or method names longer than 30 | ||
| # chars, but lots of test methods do (and should) have longer names. It'd | ||
| # be better to restrict this setting to tests only. | ||
| # | ||
| # This also allows capital letters in function and method names (just not | ||
| # at the start), to allow names like | ||
| # test_instance_conforms_to_IDataManager(). | ||
| method-rgx: '[a-z_][a-zA-Z0-9_]{2,64}$' | ||
| function-rgx: '[a-z_][a-zA-Z0-9_]{2,64}$' | ||
| method-rgx: '((test_[a-z0-9_]{2,59})|([a-z_][a-z0-9_]{2,30}))$' | ||
| function-rgx: '((test_[a-z0-9_]{2,59})|([a-z_][a-z0-9_]{2,30}))$' | ||
| pep257: | ||
| disable: | ||
| - D100 # Missing docstring in public module | ||
| @@ -1,17 +1,18 @@ | ||
| # use Travis container build infrastructure | ||
| sudo: false | ||
| language: | ||
| - python | ||
| python: | ||
| - '2.7' | ||
| install: | ||
| - gem install sass | ||
| - gem install compass | ||
| - pip install coveralls | ||
| - pip install mandrill | ||
| - pip install pyramid_redis_sessions | ||
| - pip install -U pip wheel | ||
| - pip install coveralls pyramid_redis_sessions | ||
| - make | ||
| script: | ||
| - make test | ||
| # Run all tests, with coverage if possible | ||
| - make cover | ||
| # Test building browser extensions | ||
| - hypothesis-buildext conf/testext.ini chrome --base http://localhost | ||
| - hypothesis-buildext conf/testext.ini firefox --base http://localhost | ||
| - "hypothesis-buildext conf/production.ini chrome | ||
| @@ -22,6 +23,10 @@ script: | ||
| --assets resource://notarealkey/hypothesis/data" | ||
| after_success: | ||
| - coveralls | ||
| cache: | ||
| directories: | ||
| - node_modules | ||
| - $HOME/.cache/pip | ||
| notifications: | ||
| irc: | ||
| channels: | ||
| @@ -1,3 +1,20 @@ | ||
| 0.4.1 (2015-05-21) | ||
| ================== | ||
| - Add NIPSA flag to user table (migration needed!) | ||
| - Upgrade to Annotator v1.2.x tip (6536160) | ||
| - Hide the widget panel until ready for input (#2207) | ||
| - Fix UI z-index to actual maximum (#1909) | ||
| - Change annotation card action from 'share' to 'link' | ||
| - Add a client-side error when saving an annotation fails | ||
| - Snap the sidebar closed as well as open (#2162) | ||
| - Put NSQ usage behind feature flag. The API no longer requires NSQ. | ||
| - For development, disable WebSocket streaming, email notifications, and NSQ. | ||
| - Lots of linting. | ||
| - Added support for URL parameters to the Atom feed at ``/stream.atom``. | ||
| For example: ``/stream.atom?user=seanh`` or | ||
| ``/stream.atom?user=seanh&tags=foo,bar``. | ||
| 0.4.0 (2015-05-05) | ||
| ================== | ||
| @@ -40,6 +40,8 @@ test: | ||
| cover: | ||
| @python setup.py test --cov | ||
| @"$$(npm bin)"/karma start h/static/scripts/karma.config.js --single-run | ||
| @"$$(npm bin)"/karma start h/browser/chrome/karma.config.js --single-run | ||
| lint: | ||
| @prospector | ||
| @@ -11,7 +11,7 @@ Hypothesis | ||
| :target: https://landscape.io/github/hypothesis/h/master | ||
| :alt: Code Health | ||
| .. image:: https://img.shields.io/badge/IRC-%23hypothes.is-blue.svg | ||
| :target: https://www.irccloud.com/invite?channel=%23hypothes.is&hostname=irc.freenode.net&port=6697&ssl=1 | ||
| :target: `#hypothes.is`_ | ||
| :alt: #hypothes.is IRC channel | ||
| @@ -33,15 +33,16 @@ Hypothesis is a tool for annotating the web. | ||
| Installation and deployment | ||
| --------------------------- | ||
| See `<docs/INSTALL.rst>`_ for instructions on deploying h in a production | ||
| environment. | ||
| See the | ||
| `Installation guide <https://h.readthedocs.org/en/latest/INSTALL.html>`_ for | ||
| instructions on deploying h in a production environment. | ||
| Development | ||
| ----------- | ||
| See `<docs/hacking/install.rst>`_ for instructions on setting up a development | ||
| environment for h. | ||
| See the `Contributor's guide`_ for instructions on setting up a development | ||
| environment and contributing to h. | ||
| Community | ||
| @@ -50,16 +51,16 @@ Community | ||
| Join us in `#hypothes.is`_ on freenode_ for discussion. | ||
| If you'd like to contribute to the project, you should also `subscribe`_ to the | ||
| `development mailing list`_ and read our `contributor's guide`_. Then consider | ||
| `development mailing list`_ and read our `Contributor's guide`_. Then consider | ||
| getting started on one of the issues that are ready for work. Issues tagged with | ||
| the label '`New Contributor Friendly`_' are ideal for those just getting | ||
| started. | ||
| .. _#hypothes.is: http://webchat.freenode.net/?channels=hypothes.is | ||
| .. _#hypothes.is: https://www.irccloud.com/invite?channel=%23hypothes.is&hostname=irc.freenode.net&port=6667&ssl=1 | ||
| .. _freenode: http://freenode.net/ | ||
| .. _subscribe: mailto:dev+subscribe@list.hypothes.is | ||
| .. _development mailing list: http://list.hypothes.is/archive/ | ||
| .. _contributor's guide: CONTRIBUTING.rst | ||
| .. _development mailing list: https://groups.google.com/a/list.hypothes.is/forum/#!forum/dev | ||
| .. _Contributor's guide: https://h.readthedocs.org/en/latest/hacking/ | ||
| .. _New Contributor Friendly: https://github.com/hypothesis/h/issues?q=is%3Aopen+is%3Aissue+label%3A%22New+Contributor+Friendly%22 | ||
| @@ -58,7 +58,6 @@ secret_key: notverysecretafterall | ||
| sqlalchemy.url: sqlite:///.h.db | ||
| jinja2.extensions: h.jinja_extensions:IncludeRawExtension | ||
| jinja2.filters: json = json.dumps | ||
| webassets.base_dir: h:static | ||
| webassets.base_url: assets | ||
| @@ -57,7 +57,6 @@ sqlalchemy.url: sqlite:///.h.db | ||
| # http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/index.html#jinja2-extensions | ||
| jinja2.extensions: h.jinja_extensions:IncludeRawExtension | ||
| jinja2.filters: json = json.dumps | ||
| # Static asset configuration -- see webassets documentation | ||
| # Until the next pyramid_webassets, don't change these. | ||
| @@ -1,5 +1,5 @@ | ||
| Hacking guide | ||
| ############# | ||
| Contributor's guide | ||
| ################### | ||
| The following sections document how to setup a development environment for h | ||
| and how to contribute code or documentation to the project. | ||
| @@ -22,6 +22,22 @@ | ||
| from sqlalchemy.ext.declarative import declared_attr | ||
| # Silence some SQLAlchemy warnings caused by the Horus library. | ||
| import warnings | ||
| warnings.filterwarnings("ignore", message=r".*Unmanaged access of declarative " | ||
| "attribute __tablename__ from " | ||
| "non-mapped class UserGroupMixin") | ||
| warnings.filterwarnings("ignore", message=r".*Unmanaged access of declarative " | ||
| "attribute __tablename__ from " | ||
| "non-mapped class GroupMixin") | ||
| warnings.filterwarnings("ignore", message=r".*Unmanaged access of declarative " | ||
| "attribute __tablename__ from " | ||
| "non-mapped class ActivationMixin") | ||
| warnings.filterwarnings("ignore", message=r".*Unmanaged access of declarative " | ||
| "attribute __tablename__ from " | ||
| "non-mapped class UserMixin") | ||
| class Activation(ActivationMixin, Base): | ||
| def __init__(self, *args, **kwargs): | ||
| super(Activation, self).__init__(*args, **kwargs) | ||
| @@ -1,4 +1,5 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # pylint: disable=no-self-use | ||
| from __future__ import unicode_literals | ||
| import pytest | ||
| @@ -1,3 +1,4 @@ | ||
| # pylint: disable=no-self-use | ||
| from mock import patch, Mock, MagicMock | ||
| import pytest | ||
| @@ -57,12 +57,12 @@ def create_app(global_config, **settings): | ||
| config.add_tween('h.tweens.csrf_tween_factory') | ||
| if config.feature('accounts'): | ||
| if config.registry.feature('accounts'): | ||
| config.set_authentication_policy(session_authn) | ||
| config.set_authorization_policy(acl_authz) | ||
| config.include('h.accounts') | ||
| if config.feature('api'): | ||
| if config.registry.feature('api'): | ||
| api_app = create_api(settings) | ||
| api_view = wsgiapp2(api_app) | ||
| config.add_view(api_view, name='api', decorator=strip_vhm) | ||
| @@ -71,16 +71,16 @@ def create_app(global_config, **settings): | ||
| config.add_view(api_view, name='api', decorator=strip_vhm, | ||
| route_name='index') | ||
| if config.feature('claim'): | ||
| if config.registry.feature('claim'): | ||
| config.include('h.claim') | ||
| if config.feature('queue'): | ||
| if config.registry.feature('queue'): | ||
| config.include('h.queue') | ||
| if config.feature('streamer'): | ||
| if config.registry.feature('streamer'): | ||
| config.include('h.streamer') | ||
| if config.feature('notification'): | ||
| if config.registry.feature('notification'): | ||
| config.include('h.notification') | ||
| return config.make_wsgi_app() | ||
| @@ -106,7 +106,7 @@ def create_api(global_config, **settings): | ||
| config.include('h.api.db') | ||
| config.include('h.api.views') | ||
| if config.feature('queue'): | ||
| if config.registry.feature('queue'): | ||
| config.include('h.queue') | ||
| config.include('h.api.queue') | ||
| @@ -92,24 +92,10 @@ def asset_response_subscriber(event): | ||
| event.response.headers['Access-Control-Allow-Origin'] = '*' | ||
| def setup_jinja2_enviroment(config): | ||
| jinja2_env = config.get_jinja2_environment('__webassets__') | ||
| jinja2_env.globals['feature'] = config.feature | ||
| jinja2_env.variable_start_string = '"{{' | ||
| jinja2_env.variable_end_string = '}}"' | ||
| webassets_env = config.get_webassets_env() | ||
| webassets_env.config['jinja2_env'] = jinja2_env | ||
| def includeme(config): | ||
| config.registry.settings.setdefault('webassets.bundles', 'h:assets.yaml') | ||
| config.include('pyramid_webassets') | ||
| config.include('pyramid_jinja2') | ||
| config.add_jinja2_renderer('__webassets__') | ||
| config.action(None, setup_jinja2_enviroment, args=(config,), order=1) | ||
| # Set up a predicate and subscriber to set CORS headers on asset responses | ||
| config.add_subscriber_predicate('asset_request', AssetRequest) | ||
| config.add_subscriber( | ||
| @@ -101,13 +101,9 @@ config: | ||
| filters: uglifyjs | ||
| contents: | ||
| - output: scripts/config.js | ||
| filters: | ||
| - browserify | ||
| - jinja2 | ||
| filters: browserify | ||
| contents: | ||
| - h:static/scripts/config/features.coffee | ||
| depends: | ||
| - h:static/scripts/config/* | ||
| - h:static/scripts/config/accounts.coffee | ||
| # Application | ||
| @@ -1,3 +1,4 @@ | ||
| # pylint: disable=no-self-use | ||
| import mock | ||
| import pytest | ||
| @@ -1,4 +1,5 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # pylint: disable=no-self-use | ||
| """ | ||
| The `conftest` module is automatically loaded by py.test and serves as a place | ||
| to put fixture functions that are useful application-wide. | ||
| @@ -53,6 +53,4 @@ def _features_from_settings(settings, prefix=__package__ + '.feature.'): | ||
| def includeme(config): | ||
| def directive(config, name): | ||
| return get_client(config)(name) | ||
| config.add_directive('feature', directive) | ||
| config.registry.feature = get_client(config) | ||
| @@ -1,7 +1,5 @@ | ||
| from . import atom_feed | ||
| JINJA2_FILE_EXTENSIONS = ['.js', '.txt', '.html', '.xml'] | ||
| class AnnotationsAtomRendererFactory(object): | ||
| @@ -39,18 +37,7 @@ def __call__(self, value, system): | ||
| return atom_feed.render_annotations(request=system["request"], **value) | ||
| def setup_jinja2_environment(config, extension): | ||
| env = config.get_jinja2_environment(extension) | ||
| env.globals['feature'] = config.feature | ||
| def includeme(config): | ||
| config.add_renderer( | ||
| name="annotations_atom", | ||
| factory="h.renderers.AnnotationsAtomRendererFactory") | ||
| config.include('pyramid_jinja2') | ||
| for extension in JINJA2_FILE_EXTENSIONS: | ||
| args = (config, extension) | ||
| config.action(None, setup_jinja2_environment, args=args, order=1) | ||
| config.add_jinja2_renderer(extension) | ||
Oops, something went wrong.