Skip to content

Commit 78369ea

Browse files
committed
organize for dist as pypi package
1 parent 182cbd6 commit 78369ea

22 files changed

+267
-43
lines changed

dj_idom/consumers.py

Lines changed: 0 additions & 17 deletions
This file was deleted.

noxfile.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from __future__ import annotations
2+
3+
import os
4+
import re
5+
import subprocess
6+
from pathlib import Path
7+
from typing import List, Tuple
8+
9+
import nox
10+
from nox.sessions import Session
11+
12+
13+
HERE = Path(__file__).parent
14+
POSARGS_PATTERN = re.compile(r"^(\w+)\[(.+)\]$")
15+
16+
17+
@nox.session(reuse_venv=True)
18+
def format(session: Session) -> None:
19+
install_requirements_file(session, "check-style")
20+
session.run("black", ".")
21+
session.run("isort", ".")
22+
23+
24+
@nox.session
25+
def test(session: Session) -> None:
26+
"""Run the complete test suite"""
27+
session.install("--upgrade", "pip", "setuptools", "wheel")
28+
test_suite(session)
29+
test_style(session)
30+
31+
32+
@nox.session
33+
def test_suite(session: Session) -> None:
34+
"""Run the Python-based test suite"""
35+
session.env["IDOM_DEBUG_MODE"] = "1"
36+
install_requirements_file(session, "test-env")
37+
session.install(".[all]")
38+
session.run("figure-it-out")
39+
40+
41+
@nox.session
42+
def test_style(session: Session) -> None:
43+
"""Check that style guidelines are being followed"""
44+
install_requirements_file(session, "check-style")
45+
session.run("flake8", "src/django_idom", "tests")
46+
black_default_exclude = r"\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist"
47+
session.run(
48+
"black",
49+
".",
50+
"--check",
51+
"--exclude",
52+
rf"/({black_default_exclude}|venv|node_modules)/",
53+
)
54+
session.run("isort", ".", "--check-only")
55+
56+
57+
def install_requirements_file(session: Session, name: str) -> None:
58+
file_path = HERE / "requirements" / (name + ".txt")
59+
assert file_path.exists(), f"requirements file {file_path} does not exist"
60+
session.install("-r", str(file_path))

pyproject.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[build-system]
2+
requires = ["setuptools>=42", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[tool.isort]
6+
multi_line_output = 3
7+
force_grid_wrap = 0
8+
use_parentheses = "True"
9+
ensure_newline_before_comments = "True"
10+
include_trailing_comma = "True"
11+
line_length = 88
12+
lines_after_imports = 2

requirements.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
django<4.0.0 # Django Library
2-
daphne<4.0.0 # Production ASGI webserver
3-
channels<4.0.0 # Django websocket features
4-
idom<1.0.0 # Python React
1+
-r requirements/pkg-deps.txt
2+
-r requirements/check-style.txt
3+
-r requirements/test-env.txt
4+
-r requirements/test-run.txt

requirements/check-style.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
black
2+
flake8
3+
isort

requirements/pkg-deps.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
channels<4.0.0 # Django websocket features
2+
idom<1.0.0 # Python React

requirements/test-env.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
django<4.0.0 # Django Library
2+
daphne<4.0.0 # Production ASGI webserver

requirements/test-run.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nox

setup.cfg

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[bdist_wheel]
2+
universal=1
3+
4+
[flake8]
5+
ignore = E203, E266, E501, W503, F811, N802
6+
max-line-length = 88
7+
max-complexity = 18
8+
select = B,C,E,F,W,T4,B9,N,ROH
9+
exclude =
10+
.eggs/*
11+
.nox/*

setup.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import os
2+
import sys
3+
from pathlib import Path
4+
5+
from setuptools import find_packages, setup
6+
7+
8+
# the name of the project
9+
name = "django_idom"
10+
11+
# basic paths used to gather files
12+
root_dir = Path(__file__).parent
13+
src_dir = root_dir / "src"
14+
package_dir = src_dir / name
15+
16+
17+
# -----------------------------------------------------------------------------
18+
# Package Definition
19+
# -----------------------------------------------------------------------------
20+
21+
22+
package = {
23+
"name": name,
24+
"python_requires": ">=3.7",
25+
"packages": find_packages(str(src_dir)),
26+
"package_dir": {"": "src"},
27+
"description": "Control the web with Python",
28+
"author": "Ryan Morshead",
29+
"author_email": "ryan.morshead@gmail.com",
30+
"url": "https://github.com/idom-team/django-idom",
31+
"license": "MIT",
32+
"platforms": "Linux, Mac OS X, Windows",
33+
"keywords": ["interactive", "widgets", "DOM", "React"],
34+
"zip_safe": False,
35+
"classifiers": [
36+
"Framework :: Django",
37+
"Framework :: Django :: 3.1",
38+
"Framework :: Django :: 3.2",
39+
"Operating System :: OS Independent",
40+
"Intended Audience :: Developers",
41+
"Intended Audience :: Science/Research",
42+
"Topic :: Multimedia :: Graphics",
43+
"Programming Language :: Python :: 3.7",
44+
"Programming Language :: Python :: 3.8",
45+
"Programming Language :: Python :: 3.9",
46+
"Environment :: Web Environment",
47+
],
48+
}
49+
50+
51+
# -----------------------------------------------------------------------------
52+
# Library Version
53+
# -----------------------------------------------------------------------------
54+
55+
with open(os.path.join(package_dir, "__init__.py")) as f:
56+
for line in f.read().split("\n"):
57+
if line.startswith("__version__ = "):
58+
package["version"] = eval(line.split("=", 1)[1])
59+
break
60+
else:
61+
print("No version found in %s/__init__.py" % package_dir)
62+
sys.exit(1)
63+
64+
65+
# -----------------------------------------------------------------------------
66+
# Requirements
67+
# -----------------------------------------------------------------------------
68+
69+
70+
requirements = []
71+
with (root_dir / "requirements" / "pkg-deps.txt").open() as f:
72+
for line in map(str.strip, f):
73+
if not line.startswith("#"):
74+
requirements.append(line)
75+
package["install_requires"] = requirements
76+
77+
78+
# -----------------------------------------------------------------------------
79+
# Library Description
80+
# -----------------------------------------------------------------------------
81+
82+
83+
with (root_dir / "README.md").open() as f:
84+
long_description = f.read()
85+
86+
package["long_description"] = long_description
87+
package["long_description_content_type"] = "text/markdown"
88+
89+
90+
# -----------------------------------------------------------------------------
91+
# Install It
92+
# -----------------------------------------------------------------------------
93+
94+
95+
if __name__ == "__main__":
96+
setup(**package)

src/django_idom/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
__version__ = "0.0.1"
2+
3+
from .websocket_consumer import IdomAsyncWebSocketConsumer
4+
5+
__all__ = ["IdomAsyncWebSocketConsumer"]

src/django_idom/websocket_consumer.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Anything used to construct a websocket endpoint"""
2+
import asyncio
3+
from typing import Any
4+
5+
from channels.generic.websocket import AsyncJsonWebsocketConsumer
6+
7+
from idom.core.dispatcher import dispatch_single_view
8+
from idom.core.component import ComponentConstructor
9+
10+
11+
class IdomAsyncWebSocketConsumer(AsyncJsonWebsocketConsumer):
12+
"""Communicates with the browser to perform actions on-demand."""
13+
14+
def __init__(
15+
self, component: ComponentConstructor, *args: Any, **kwargs: Any
16+
) -> None:
17+
self._idom_component_constructor = component
18+
super().__init__(*args, **kwargs)
19+
20+
async def connect(self) -> None:
21+
self._idom_recv_queue = recv_queue = asyncio.Queue()
22+
self._idom_dispatcher_future = dispatch_single_view(
23+
self._idom_component_constructor,
24+
self.send_json,
25+
recv_queue.get,
26+
)
27+
28+
async def close(self, *args: Any, **kwargs: Any) -> None:
29+
self._idom_dispatcher_future.cancel()
30+
await asyncio.wait([self._idom_dispatcher_future])
31+
super().close(*args, **kwargs)
32+
33+
async def receive_json(self, content: Any, **kwargs: Any) -> None:
34+
await self._idom_recv_queue.put(content)

manage.py renamed to tests/manage.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
def main():
88
"""Run administrative tasks."""
9-
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dj_idom.settings')
9+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings")
1010
try:
1111
from django.core.management import execute_from_command_line
1212
except ImportError as exc:
@@ -18,5 +18,5 @@ def main():
1818
execute_from_command_line(sys.argv)
1919

2020

21-
if __name__ == '__main__':
21+
if __name__ == "__main__":
2222
main()
File renamed without changes.

dj_idom/asgi.py renamed to tests/tests/asgi.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
ASGI config for dj_idom project.
2+
ASGI config for tests project.
33
44
It exposes the ASGI callable as a module-level variable named ``application``.
55
@@ -12,18 +12,22 @@
1212
from django.conf.urls import url
1313
from django.core.asgi import get_asgi_application
1414

15-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dj_idom.settings")
15+
from .views import HelloWorld
16+
17+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings")
1618

1719
# Fetch ASGI application before importing dependencies that require ORM models.
1820
http_asgi_app = get_asgi_application()
1921

2022
from channels.routing import ProtocolTypeRouter, URLRouter
2123

22-
from .consumers import CommandConsumer
24+
from django_idom import IdomAsyncWebSocketConsumer
2325

2426
application = ProtocolTypeRouter(
2527
{
2628
"http": http_asgi_app,
27-
"websocket": URLRouter([url("", CommandConsumer().as_asgi())]),
29+
"websocket": URLRouter(
30+
[url("", IdomAsyncWebSocketConsumer.as_asgi(component=HelloWorld))]
31+
),
2832
}
2933
)

tests/tests/migrations/__init__.py

Whitespace-only changes.

dj_idom/settings.py renamed to tests/tests/settings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Django settings for dj_idom project.
2+
Django settings for tests project.
33
44
Generated by 'django-admin startproject' using Django 3.2.3.
55
@@ -50,12 +50,12 @@
5050
"django.middleware.clickjacking.XFrameOptionsMiddleware",
5151
]
5252

53-
ROOT_URLCONF = "dj_idom.urls"
53+
ROOT_URLCONF = "tests.urls"
5454

5555
TEMPLATES = [
5656
{
5757
"BACKEND": "django.template.backends.django.DjangoTemplates",
58-
"DIRS": [os.path.join(BASE_DIR, "dj_idom", "templates")],
58+
"DIRS": [os.path.join(BASE_DIR, "tests", "templates")],
5959
"APP_DIRS": True,
6060
"OPTIONS": {
6161
"context_processors": [
@@ -68,7 +68,7 @@
6868
},
6969
]
7070

71-
ASGI_APPLICATION = "dj_idom.asgi.application"
71+
ASGI_APPLICATION = "tests.asgi.application"
7272

7373

7474
# Database
@@ -127,5 +127,5 @@
127127

128128
# Static Files (CSS, JavaScript, Images)
129129
STATICFILES_DIRS = [
130-
os.path.join(BASE_DIR, "dj_idom", "static"),
130+
os.path.join(BASE_DIR, "tests", "static"),
131131
]
File renamed without changes.
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
{% load static %}
22
<!DOCTYPE html>
33
<html lang="en">
4-
5-
<head>
6-
<meta charset="UTF-8">
7-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
8-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
4+
<head>
5+
<meta charset="UTF-8" />
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
98
<script src="{% static 'scripts.js' %}" crossorigin="anonymous"></script>
109
<title>IDOM</title>
11-
</head>
10+
</head>
1211

13-
<body>
12+
<body>
1413
<h1>IDOM Test Page</h1>
15-
</body>
16-
17-
</html>
14+
</body>
15+
</html>

tests/tests/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

0 commit comments

Comments
 (0)