diff --git a/.gitignore b/.gitignore index d497ce8..595f282 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ __pycache__ stickynotes.cfg build dist +.coverage +htmlcov diff --git a/.woodpecker.yaml b/.woodpecker.yaml new file mode 100644 index 0000000..90124c0 --- /dev/null +++ b/.woodpecker.yaml @@ -0,0 +1,23 @@ +steps: + lint: + image: python:3.11 + commands: + - pip install hatch + - hatch run lint:run + test: + image: python:3.11 + commands: + - pip install hatch + - cp stickynotes.example.cfg stickynotes.cfg + - hatch run tests:run + publish-package: + image: python:3.11 + commands: + - pip install hatch + - hatch publish --repo $PIP_REPOSITORY --user $PIP_USERNAME --auth $PIP_TOKEN --no-prompt + secrets: + - pip_repository + - pip_username + - pip_token + when: + event: tag diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..26a736e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.11 + +RUN pip install stickynotes --index-url https://git.snyman.info/packages/raoul/index + +EXPOSE 8000 +CMD ["hypercorn", "stickynotes.app"] diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..38d57af --- /dev/null +++ b/README.rst @@ -0,0 +1,33 @@ +=========== +StickyNotes +=========== + +StickyNotes is a simple "pastebin" written in Python using Quart, SQLAlchemy, Pygments and a few other libraries. + +Installation +------------ + +The easiest way to install StickyNotes is via Docker and Docker Compose. Here's an example config: + +.. code-block:: yaml + + version: '3' + services: + postgres: + image: postgres:15 + env: + - POSTGRES_USER=stickynotes + - POSTGRES_DB=stickynotes + - POSTGRES_PASSWORD=stickynotes + restart: unless-stopped + volumes: + - "./data/postgres:/var/lib/postgresql/data" + app: + image: git.snyman.info/raoul/stickynotes:latest + env: + - SQLALCHEMY_URL=postgres://stickynotes:stickynotes@postgres/stickynotes + restart: unless-stopped + ports: + - "127.0.0.1:8000:8000" + +Once you have that up and running, you can set up NGINX or another reverse proxy to port 8000 on 127.0.0.1. diff --git a/pyproject.toml b/pyproject.toml index c98b5f5..efe092e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,8 +37,6 @@ dependencies = [ "nord-pygments", "psycopg2_binary", "Pygments", - "requests", - "short_url", ] [project.optional-dependencies] @@ -59,4 +57,23 @@ include = [ ] [tool.hatch.envs.default.scripts] -server = "quart -A stickynotes.app run" +serve = "quart -A stickynotes.app run" + +[tool.hatch.envs.lint] +skip-install = true +dependencies = [ + "flake8" +] + +[tool.hatch.envs.lint.scripts] +run = "flake8" + +[tool.hatch.envs.tests] +dependencies = [ + "pytest-asyncio", + "pytest-cov", + "pytest", +] + +[tool.hatch.envs.tests.scripts] +run = "pytest --cov=stickynotes --cov-report=html" diff --git a/setup.py b/setup.py deleted file mode 100644 index 01dcd75..0000000 --- a/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -from setuptools import setup - - -setup( - name='StickyNotes', - version='0.2', - author='Raoul Snyman', - description='A simple pastebin', - url='https://bin.snyman.info', - license='GPLv3+', - packages=['stickynotes'], - include_package_data=True, - platforms='any', - python_requires='>=3.5', - install_requires=[ - 'Flask', - 'Flask-SQLAlchemy', - 'Pygments', - 'requests', - 'short_url', - 'psycopg2_binary', - 'nord-pygments' - ], - extras_require={ - 'dev': [ - 'pytest>=3', - 'pytest-cov', - ], - }, - classifiers=[ - 'Development Status :: 2 - Pre-Alpha', - 'Environment :: Web Environment', - 'Framework :: Flask', - 'Intended Audience :: Other Audience', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3 :: Only', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Content Management System', - 'Topic :: Internet :: WWW/HTTP :: WSGI', - 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', - ], -) diff --git a/stickynotes.example.cfg b/stickynotes.example.cfg index 89a739f..9ecb6b4 100644 --- a/stickynotes.example.cfg +++ b/stickynotes.example.cfg @@ -1,5 +1,3 @@ [stickynotes] -sqlalchemy_database_uri = sqlite:///stickynotes.sqlite +sqlalchemy_database_uri = sqlite:/// secret_key = yoursecretkeyhere -recaptcha_site_key = -recaptcha_secret_key = diff --git a/stickynotes/static/stickynotes.png b/stickynotes/static/stickynotes.png new file mode 100644 index 0000000..03f2261 Binary files /dev/null and b/stickynotes/static/stickynotes.png differ diff --git a/stickynotes/static/stickynotes.svg b/stickynotes/static/stickynotes.svg new file mode 100644 index 0000000..b8dba7d --- /dev/null +++ b/stickynotes/static/stickynotes.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + diff --git a/stickynotes/views.py b/stickynotes/views.py index 14a36a1..6b57417 100644 --- a/stickynotes/views.py +++ b/stickynotes/views.py @@ -59,7 +59,7 @@ async def notes(): .filter(or_(StickyNote.expiry == None, StickyNote.expiry < datetime.utcnow()))\ .filter(~StickyNote.private)\ .order_by(StickyNote.created.desc())\ - .limit(10) # noqa + .limit(10) # noqa: E711 return await render_template('notes.html', notes=notes) diff --git a/tests/test_views.py b/tests/test_views.py new file mode 100644 index 0000000..9c11ebf --- /dev/null +++ b/tests/test_views.py @@ -0,0 +1,16 @@ +import pytest + +from stickynotes.app import make_app + +pytestmark = [pytest.mark.asyncio] + + +@pytest.fixture +def app(): + return make_app() + + +async def test_index(app): + test_client = app.test_client() + response = await test_client.get('/') + assert response.status_code == 200