]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Create two different python distributions in the project
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 25 Jul 2020 23:54:32 +0000 (00:54 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 5 Aug 2020 01:48:40 +0000 (02:48 +0100)
The psycopg3 package is pure Python and doesn't depend on Cython, the
psycopg3_c package is entirely optional and depends on the former.

Tox had to be split, because it gets confused by the presence of the
top-level pyproject.toml, which is there only to configure black.

74 files changed:
.gitignore
.travis.yml
MANIFEST.in [deleted file]
README.rst
psycopg3/.gitignore
psycopg3/.mypy.ini [moved from .mypy.ini with 87% similarity]
psycopg3/LICENSE.txt [new symlink]
psycopg3/MANIFEST.in [new file with mode: 0644]
psycopg3/README.rst [new file with mode: 0644]
psycopg3/consts.py [deleted file]
psycopg3/pq/.gitignore [deleted file]
psycopg3/psycopg3/__init__.py [moved from psycopg3/__init__.py with 92% similarity]
psycopg3/psycopg3/adapt.py [moved from psycopg3/adapt.py with 99% similarity]
psycopg3/psycopg3/connection.py [moved from psycopg3/connection.py with 99% similarity]
psycopg3/psycopg3/conninfo.py [moved from psycopg3/conninfo.py with 100% similarity]
psycopg3/psycopg3/copy.py [moved from psycopg3/copy.py with 100% similarity]
psycopg3/psycopg3/cursor.py [moved from psycopg3/cursor.py with 99% similarity]
psycopg3/psycopg3/dbapi20.py [moved from psycopg3/dbapi20.py with 100% similarity]
psycopg3/psycopg3/errors.py [moved from psycopg3/errors.py with 100% similarity]
psycopg3/psycopg3/generators.py [moved from psycopg3/generators.py with 100% similarity]
psycopg3/psycopg3/pq/__init__.py [moved from psycopg3/pq/__init__.py with 97% similarity]
psycopg3/psycopg3/pq/_pq_ctypes.py [moved from psycopg3/pq/_pq_ctypes.py with 100% similarity]
psycopg3/psycopg3/pq/_pq_ctypes.pyi [moved from psycopg3/pq/_pq_ctypes.pyi with 100% similarity]
psycopg3/psycopg3/pq/encodings.py [moved from psycopg3/pq/encodings.py with 100% similarity]
psycopg3/psycopg3/pq/enums.py [moved from psycopg3/pq/enums.py with 100% similarity]
psycopg3/psycopg3/pq/misc.py [moved from psycopg3/pq/misc.py with 100% similarity]
psycopg3/psycopg3/pq/pq_ctypes.py [moved from psycopg3/pq/pq_ctypes.py with 100% similarity]
psycopg3/psycopg3/pq/proto.py [moved from psycopg3/pq/proto.py with 100% similarity]
psycopg3/psycopg3/proto.py [moved from psycopg3/proto.py with 100% similarity]
psycopg3/psycopg3/transform.py [moved from psycopg3/transform.py with 100% similarity]
psycopg3/psycopg3/types/__init__.py [moved from psycopg3/types/__init__.py with 100% similarity]
psycopg3/psycopg3/types/array.py [moved from psycopg3/types/array.py with 100% similarity]
psycopg3/psycopg3/types/composite.py [moved from psycopg3/types/composite.py with 100% similarity]
psycopg3/psycopg3/types/numeric.py [moved from psycopg3/types/numeric.py with 100% similarity]
psycopg3/psycopg3/types/oids.py [moved from psycopg3/types/oids.py with 100% similarity]
psycopg3/psycopg3/types/text.py [moved from psycopg3/types/text.py with 100% similarity]
psycopg3/psycopg3/utils/__init__.py [moved from psycopg3/utils/__init__.py with 100% similarity]
psycopg3/psycopg3/utils/queries.py [moved from psycopg3/utils/queries.py with 100% similarity]
psycopg3/psycopg3/version.py [new file with mode: 0644]
psycopg3/psycopg3/waiting.py [moved from psycopg3/waiting.py with 100% similarity]
psycopg3/pyproject.toml [new file with mode: 0644]
psycopg3/setup.cfg [new file with mode: 0644]
psycopg3/setup.py [new file with mode: 0644]
psycopg3/tox.ini [new file with mode: 0644]
psycopg3_c/.gitignore [new file with mode: 0644]
psycopg3_c/LICENSE.txt [new symlink]
psycopg3_c/MANIFEST.in [new file with mode: 0644]
psycopg3_c/README.rst [new file with mode: 0644]
psycopg3_c/psycopg3_c/.gitignore [new file with mode: 0644]
psycopg3_c/psycopg3_c/__init__.py [new file with mode: 0644]
psycopg3_c/psycopg3_c/_psycopg3.pyi [moved from psycopg3/_psycopg3.pyi with 89% similarity]
psycopg3_c/psycopg3_c/_psycopg3.pyx [moved from psycopg3/_psycopg3.pyx with 100% similarity]
psycopg3_c/psycopg3_c/adapt.pxd [moved from psycopg3/adapt.pxd with 100% similarity]
psycopg3_c/psycopg3_c/adapt.pyx [moved from psycopg3/adapt.pyx with 95% similarity]
psycopg3_c/psycopg3_c/endian.pxd [moved from psycopg3/types/endian.pxd with 100% similarity]
psycopg3_c/psycopg3_c/generators.pyx [moved from psycopg3/generators.pyx with 95% similarity]
psycopg3_c/psycopg3_c/libpq.pxd [moved from psycopg3/pq/libpq.pxd with 100% similarity]
psycopg3_c/psycopg3_c/pq_cython.pxd [moved from psycopg3/pq/pq_cython.pxd with 95% similarity]
psycopg3_c/psycopg3_c/pq_cython.pyx [moved from psycopg3/pq/pq_cython.pyx with 99% similarity]
psycopg3_c/psycopg3_c/transform.pyx [moved from psycopg3/transform.pyx with 98% similarity]
psycopg3_c/psycopg3_c/types/numeric.pyx [moved from psycopg3/types/numeric.pyx with 96% similarity]
psycopg3_c/psycopg3_c/types/text.pyx [moved from psycopg3/types/text.pyx with 98% similarity]
psycopg3_c/psycopg3_c/version.py [new file with mode: 0644]
psycopg3_c/pyproject.toml [new file with mode: 0644]
psycopg3_c/setup.cfg [new file with mode: 0644]
psycopg3_c/setup.py [new file with mode: 0644]
psycopg3_c/tox.ini [new file with mode: 0644]
pyproject.toml
setup.py [deleted file]
tests/fix_db.py
tests/fix_pq.py
tests/pq/test_pgconn.py
tests/test_concurrency.py
tox.ini

index ce69c0448fa0de261cf0f47a3ca0449d94b93e3f..54ca4839adaf13bcfa6093b2279945a92b2654d7 100644 (file)
@@ -1,6 +1,6 @@
-/psycopg3.egg-info
-/.tox
-/.eggs
+/*.egg-info/
+.tox
+/.eggs/
 /build
 /dist
 *.pstats
index a23c2b4dd54f8864c537903c6105e1362d35856c..0520f9d29578b7652598706642206c3b649ae1e3 100644 (file)
@@ -9,13 +9,19 @@ env:
 matrix:
   include:
 
-    - env: TOXENV=black
+    - env:
+        - TOXENV=black
+        - TOXDIR=.
       python: 3.6
 
-    - env: TOXENV=flake8
+    - env:
+        - TOXENV=flake8
+        - TOXDIR=.
       python: 3.6
 
-    - env: TOXENV=mypy
+    - env:
+        - TOXENV=mypy
+        - TOXDIR=.
       python: 3.6
 
     - python: 3.6
@@ -26,6 +32,7 @@ matrix:
             - postgresql-client-9.5
       env:
         - TOXENV=py36
+        - TOXDIR=psycopg3_c
         - PGVER=9.5
         - PSYCOPG3_IMPL=c
         - PGPORT=5432
@@ -38,6 +45,7 @@ matrix:
             - postgresql-client-9.6
       env:
         - TOXENV=py36
+        - TOXDIR=psycopg3
         - PGVER=9.6
         - PSYCOPG3_IMPL=ctypes
         - PGPORT=5432
@@ -50,6 +58,7 @@ matrix:
             - postgresql-client-10
       env:
         - TOXENV=py37
+        - TOXDIR=psycopg3_c
         - PGVER=10
         - PSYCOPG3_IMPL=c
         - PGPORT=5432
@@ -63,6 +72,7 @@ matrix:
             - postgresql-client-11
       env:
         - TOXENV=py37
+        - TOXDIR=psycopg3
         - PGVER=11
         - PSYCOPG3_IMPL=ctypes
         - PGPORT=5433
@@ -76,6 +86,7 @@ matrix:
             - postgresql-client-12
       env:
         - TOXENV=py38
+        - TOXDIR=psycopg3_c
         - PGVER=12
         - PSYCOPG3_IMPL=c
         - PGPORT=5433
@@ -89,6 +100,7 @@ matrix:
             - postgresql-client-12
       env:
         - TOXENV=py38
+        - TOXDIR=psycopg3
         - PGVER=12
         - PSYCOPG3_IMPL=ctypes
         - PGPORT=5433
@@ -98,4 +110,4 @@ install:
   - test ${TOXENV:0:2} != py || psql -c 'create database psycopg3_test'
 
 script:
-  - tox
+  - tox -c $TOXDIR
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644 (file)
index 10984ce..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-include README.rst LICENSE.txt BACKERS.md tox.ini
-recursive-include psycopg3 *.pyx *.pxd
index 162debd06872c0385eabb8108eebc9414f871a30..51ca1d1e6fe352c35d3c81fce2e868cb89eef33c 100644 (file)
@@ -3,6 +3,15 @@ psycopg3 -- PostgreSQL database adapter for Python
 
 psycopg3 is a modern implementation of a PostgreSQL adapter for Python.
 
+The package is split in different parts, with different requirements.
+
+- The pure python package only depends on the **libpq**, the PostgreSQL client
+  library. The code is in the ``psycopg3`` directory.
+
+- The optional C optimization: in order to build it requires the **libpq-dev**
+  packages, a C compiler and Cython. The code is in the ``psycopg3_c``
+  directory.
+
 
 Installation
 ------------
@@ -10,7 +19,10 @@ Installation
 The library is still in early development stage. If you want to try it out you
 can install it from source using::
 
-    pip install -e git+https://github.com/psycopg/psycopg3.git#egg=psycopg3
+    git clone https://github.com/psycopg/psycopg3.git
+    cd psycopg3
+    python psycopg3/setup.py install    # for the base Python package
+    python psycopg3_c/setup.py install  # for the C extension module
 
 
 Hacking
@@ -19,16 +31,20 @@ Hacking
 We assume you have built your virtualenv and ``pip`` just works and ``python``
 refers to Python 3. You can set up a dev environment with::
 
-    python setup.py develop
+    python psycopg3/setup.py develop    # for the base Python pacakge
+    python psycopg3_c/setup.py develop  # for the C extension module
 
-All the available tests and dev support are defined in ``tox.ini``: please
-refer to `tox documentation`__ for its usage. You can run all the tests with::
+All the available tests and dev support are defined in the ``tox.ini`` files
+in this directory and in the package directories: please refer to `tox
+documentation`__ for its usage. You can run all the tests with::
 
     psql -c 'create database psycopg3_test'
     export PSYCOPG3_TEST_DSN="dbname=psycopg3_test"
-    tox -s
+    tox -c psycopg3 -s
+    tox -c psycopg3_c -s
+
+and validate the code before submission running::
 
-You can also install the test dependencies in your virtualenv to run tests
-faster: please look at the ``tox.ini`` comments for instructions.
+    tox -p4
 
 .. __: https://tox.readthedocs.io/
index f14a44ed80626d180743fa35275dfdde152f5ee9..4bba7db84a501861cd403d0bb0d19914384049be 100644 (file)
@@ -1,3 +1,3 @@
-_psycopg3.c
-_psycopg3.*.so
-*.html
+/psycopg3.egg-info/
+/build
+/dist
similarity index 87%
rename from .mypy.ini
rename to psycopg3/.mypy.ini
index 793fbaadb0e23a9af2f9c3f01d0dbc2cc1ded62a..b62d8e3d8de21e4869d6ecdee957b6a19337b836 100644 (file)
--- a/.mypy.ini
@@ -3,6 +3,7 @@ files = psycopg3
 warn_unused_ignores = True
 show_error_codes = True
 strict = True
+mypy_path = ../psycopg3_c
 
 [mypy-pytest]
 ignore_missing_imports = True
diff --git a/psycopg3/LICENSE.txt b/psycopg3/LICENSE.txt
new file mode 120000 (symlink)
index 0000000..4ab4373
--- /dev/null
@@ -0,0 +1 @@
+../LICENSE.txt
\ No newline at end of file
diff --git a/psycopg3/MANIFEST.in b/psycopg3/MANIFEST.in
new file mode 100644 (file)
index 0000000..88629c9
--- /dev/null
@@ -0,0 +1 @@
+include README.rst LICENSE.txt
diff --git a/psycopg3/README.rst b/psycopg3/README.rst
new file mode 100644 (file)
index 0000000..36ee00d
--- /dev/null
@@ -0,0 +1,17 @@
+PostgreSQL database adapter for Python
+======================================
+
+This distribution contains the pure Python package ``psycopg3``.
+
+Installation::
+
+    pip install psycopg3
+
+Even if the package is pure Python, the PostgreSQL client library libpq must
+be available in the system.
+
+Please read `the project readme`__ for more details.
+
+.. __: https://github.com/psycopg/psycopg3#readme
+
+Copyright (C) 2020 The Psycopg Team
diff --git a/psycopg3/consts.py b/psycopg3/consts.py
deleted file mode 100644 (file)
index ae40387..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-"""
-psycopg3 package constants
-"""
-
-# Copyright (C) 2020 The Psycopg Team
-
-VERSION = "2.99.0"
diff --git a/psycopg3/pq/.gitignore b/psycopg3/pq/.gitignore
deleted file mode 100644 (file)
index 7b43893..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-pq_cython.c
-pq_cython.*.so
-pq_cython.html
similarity index 92%
rename from psycopg3/__init__.py
rename to psycopg3/psycopg3/__init__.py
index 09c7fa1733910e21d2f31f74f62a6082d0493443..aeb87d83b700e525b983232e05548f495eaec47b 100644 (file)
@@ -5,7 +5,6 @@ psycopg3 -- PostgreSQL database adapter for Python
 # Copyright (C) 2020 The Psycopg Team
 
 from . import pq
-from .consts import VERSION as __version__  # noqa
 from .connection import AsyncConnection, Connection
 
 from .errors import (
@@ -25,6 +24,8 @@ from .dbapi20 import BINARY, DATETIME, NUMBER, ROWID, STRING
 from .dbapi20 import Binary, Date, DateFromTicks, Time, TimeFromTicks
 from .dbapi20 import Timestamp, TimestampFromTicks
 
+from .version import __version__  # noqa
+
 # DBAPI compliancy
 connect = Connection.connect
 apilevel = "2.0"
@@ -37,7 +38,7 @@ from . import types  # noqa
 
 # Override adapters with fast version if available
 if pq.__impl__ == "c":
-    from ._psycopg3 import register_builtin_c_loaders
+    from psycopg3_c._psycopg3 import register_builtin_c_loaders
 
     register_builtin_c_loaders()
 
similarity index 99%
rename from psycopg3/adapt.py
rename to psycopg3/psycopg3/adapt.py
index d3fc9c78d65e527a7457e3abe8932377143aac5a..da173d6b7dcff3f38268ec284c0c69b780e3daa7 100644 (file)
@@ -156,7 +156,7 @@ Transformer: Type[proto.Transformer]
 
 # Override it with fast object if available
 if pq.__impl__ == "c":
-    from . import _psycopg3
+    from psycopg3_c import _psycopg3
 
     Transformer = _psycopg3.Transformer
 else:
similarity index 99%
rename from psycopg3/connection.py
rename to psycopg3/psycopg3/connection.py
index 597a1d430f1716c0bdd05ae1b6eae1884e5940cc..0f0e320da309c0423b7daecc809c99e0367dcd3f 100644 (file)
@@ -29,7 +29,7 @@ connect: Callable[[str], proto.PQGen[pq.proto.PGconn]]
 execute: Callable[[pq.proto.PGconn], proto.PQGen[List[pq.proto.PGresult]]]
 
 if pq.__impl__ == "c":
-    from . import _psycopg3
+    from psycopg3_c import _psycopg3
 
     connect = _psycopg3.connect
     execute = _psycopg3.execute
similarity index 100%
rename from psycopg3/copy.py
rename to psycopg3/psycopg3/copy.py
similarity index 99%
rename from psycopg3/cursor.py
rename to psycopg3/psycopg3/cursor.py
index fd4e60252ed59f047591e28cee8cb9eb387db75f..3f8cb74b460c82f87c405c94a1dbb0909885b56e 100644 (file)
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
 execute: Callable[[pq.proto.PGconn], PQGen[List[pq.proto.PGresult]]]
 
 if pq.__impl__ == "c":
-    from . import _psycopg3
+    from psycopg3_c import _psycopg3
 
     execute = _psycopg3.execute
 
similarity index 97%
rename from psycopg3/pq/__init__.py
rename to psycopg3/psycopg3/pq/__init__.py
index f4b12889e85bb70138894cb635f9db2596f3e183..f13d240d34edac7df1fa310dac73bc64a99e8f40 100644 (file)
@@ -48,7 +48,7 @@ def import_from_libpq() -> None:
     if not impl or impl == "c":
         try:
             # TODO: extension module not recognised by mypy?
-            from . import pq_cython  # type: ignore
+            from psycopg3_c import pq_cython  # type: ignore
         except Exception as e:
             if not impl:
                 logger.debug("C pq wrapper not available: %s", e)
similarity index 100%
rename from psycopg3/proto.py
rename to psycopg3/psycopg3/proto.py
diff --git a/psycopg3/psycopg3/version.py b/psycopg3/psycopg3/version.py
new file mode 100644 (file)
index 0000000..e5a7632
--- /dev/null
@@ -0,0 +1,7 @@
+"""
+psycopg3 distribution version file.
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+__version__ = "2.99.0"
diff --git a/psycopg3/pyproject.toml b/psycopg3/pyproject.toml
new file mode 100644 (file)
index 0000000..fb4f1f4
--- /dev/null
@@ -0,0 +1,6 @@
+[build-system]
+requires = ["setuptools>=49.2.0", "wheel>=0.34.2"]
+build-backend = "setuptools.build_meta"
+
+[tool.black]
+line-length = 79
diff --git a/psycopg3/setup.cfg b/psycopg3/setup.cfg
new file mode 100644 (file)
index 0000000..fef979d
--- /dev/null
@@ -0,0 +1,34 @@
+[metadata]
+name = psycopg3
+description = PostgreSQL database adapter for Python
+url = https://psycopg.org/psycopg3/
+author = Daniele Varrazzo
+author_email = daniele.varrazzo@gmail.com
+license = GNU Lesser General Public License v3 (LGPLv3)
+
+project_urls =
+    Homepage = https://psycopg.org/
+    Code = https://github.com/psycopg/psycopg3
+    Issue Tracker = https://github.com/psycopg/psycopg3/issues
+    Download = https://pypi.org/project/psycopg3/
+
+classifiers =
+    Intended Audience :: Developers
+    Programming Language :: Python :: 3
+    License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
+    Topic :: Database
+    Topic :: Database :: Front-Ends
+    Topic :: Software Development
+    Topic :: Software Development :: Libraries :: Python Modules
+
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+license_file = LICENSE.txt
+
+[options]
+python_requires = >= 3.6
+packages = find:
+zip_safe = False
+include_package_data = True
+install_requires =
+    typing_extensions
diff --git a/psycopg3/setup.py b/psycopg3/setup.py
new file mode 100644 (file)
index 0000000..80bb67f
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+"""
+PostgreSQL database adapter for Python - pure Python package
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+import re
+import os
+
+from setuptools import setup
+
+# Move to the directory of setup.py: executing this file from another location
+# (e.g. from the project root) will fail
+here = os.path.abspath(os.path.dirname(__file__))
+if os.path.abspath(os.getcwd()) != here:
+    os.chdir(here)
+
+with open("psycopg3/version.py") as f:
+    data = f.read()
+    m = re.search(r"""(?m)^__version__\s*=\s*['"]([^'"]+)['"]""", data)
+    if m is None:
+        raise Exception(f"cannot find version in {f.name}")
+    version = m.group(1)
+
+setup(version=version)
diff --git a/psycopg3/tox.ini b/psycopg3/tox.ini
new file mode 100644 (file)
index 0000000..f59f74e
--- /dev/null
@@ -0,0 +1,11 @@
+[tox]
+envlist = py{36,37,38}
+isolated_build = True
+
+[testenv:py{36,37,38}]
+commands =
+    pytest ../tests
+passenv = PG* PSYCOPG3_TEST_DSN PYTEST_ADDOPTS PSYCOPG3_IMPL
+deps =
+    pytest >= 5.3, < 6
+    pytest-asyncio >= 0.12.0, < 0.13
diff --git a/psycopg3_c/.gitignore b/psycopg3_c/.gitignore
new file mode 100644 (file)
index 0000000..c2197d4
--- /dev/null
@@ -0,0 +1,4 @@
+/.eggs
+/build
+/dist
+/psycopg3_c.egg-info
diff --git a/psycopg3_c/LICENSE.txt b/psycopg3_c/LICENSE.txt
new file mode 120000 (symlink)
index 0000000..4ab4373
--- /dev/null
@@ -0,0 +1 @@
+../LICENSE.txt
\ No newline at end of file
diff --git a/psycopg3_c/MANIFEST.in b/psycopg3_c/MANIFEST.in
new file mode 100644 (file)
index 0000000..88629c9
--- /dev/null
@@ -0,0 +1 @@
+include README.rst LICENSE.txt
diff --git a/psycopg3_c/README.rst b/psycopg3_c/README.rst
new file mode 100644 (file)
index 0000000..9eec2e4
--- /dev/null
@@ -0,0 +1,19 @@
+PostgreSQL database adapter for Python - optimisation package
+=============================================================
+
+This distribution contains the optional optimization package ``psycopg3_c``.
+
+Installation::
+
+    pip install psycopg3-c
+
+Installing this distribution requires the ``libpq-dev`` package and other
+packages normally used to build Python C extensions. If you cannot meet these
+dependencies, don't worry: you don't need the package: please install the
+``psycopg3`` package only.
+
+Please read `the project readme`__ for more details.
+
+.. __: https://github.com/psycopg/psycopg3#readme
+
+Copyright (C) 2020 The Psycopg Team
diff --git a/psycopg3_c/psycopg3_c/.gitignore b/psycopg3_c/psycopg3_c/.gitignore
new file mode 100644 (file)
index 0000000..5905a67
--- /dev/null
@@ -0,0 +1,3 @@
+/*.so
+_psycopg3.c
+pq_cython.c
diff --git a/psycopg3_c/psycopg3_c/__init__.py b/psycopg3_c/psycopg3_c/__init__.py
new file mode 100644 (file)
index 0000000..8ab3af8
--- /dev/null
@@ -0,0 +1,7 @@
+"""
+psycopg3 -- PostgreSQL database adapter for Python -- C optimization package
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+from .version import __version__  # noqa
similarity index 89%
rename from psycopg3/_psycopg3.pyi
rename to psycopg3_c/psycopg3_c/_psycopg3.pyi
index 87cd90596116f44093917eb349681fc1f11879dc..aaa29883400b2310f24bcc656b1d845f70a5b3de 100644 (file)
@@ -10,10 +10,10 @@ information. Will submit a bug.
 import codecs
 from typing import Any, Iterable, List, Optional, Sequence, Tuple
 
-from .proto import AdaptContext, DumpFunc, DumpersMap, DumperType
-from .proto import LoadFunc, LoadersMap, LoaderType, MaybeOid, PQGen
-from .connection import BaseConnection
-from . import pq
+from psycopg3.proto import AdaptContext, DumpFunc, DumpersMap, DumperType
+from psycopg3.proto import LoadFunc, LoadersMap, LoaderType, MaybeOid, PQGen
+from psycopg3.connection import BaseConnection
+from psycopg3 import pq
 
 class Transformer:
     def __init__(self, context: AdaptContext = None): ...
similarity index 95%
rename from psycopg3/adapt.pyx
rename to psycopg3_c/psycopg3_c/adapt.pyx
index 0cd43da6874b1ca07ae821840836a9c29ec51fcf..08f6409bd8d6a741a569df3b99860252d6439a0e 100644 (file)
@@ -13,7 +13,7 @@ equivalent C implementations.
 
 # Copyright (C) 2020 The Psycopg Team
 
-from psycopg3.adapt cimport cloader_func, get_context_func
+from psycopg3_c.adapt cimport cloader_func, get_context_func
 
 import logging
 logger = logging.getLogger("psycopg3.adapt")
similarity index 95%
rename from psycopg3/generators.pyx
rename to psycopg3_c/psycopg3_c/generators.pyx
index b11f5be2cd398a4c1be29f1659ad61b2f697176c..58fffc95e83e8be7720fa05240156df6843b6c8a 100644 (file)
@@ -7,12 +7,12 @@ C implementation of generators for the communication protocols with the libpq
 import logging
 from typing import List
 
-from . import errors as e
-from .proto import PQGen
-from .waiting import Wait, Ready
+from psycopg3 import errors as e
+from psycopg3.proto import PQGen
+from psycopg3.waiting import Wait, Ready
 from psycopg3 import pq
-from psycopg3.pq cimport libpq
-from psycopg3.pq.pq_cython cimport PGconn, PGresult
+from psycopg3_c cimport libpq
+from psycopg3_c.pq_cython cimport PGconn, PGresult
 
 cdef object WAIT_W = Wait.W
 cdef object WAIT_R = Wait.R
similarity index 95%
rename from psycopg3/pq/pq_cython.pxd
rename to psycopg3_c/psycopg3_c/pq_cython.pxd
index 289aea2e022cdfc2068c386dbab9c2171ab9d5b9..edfe82c8c6caa8fee30cd4e10af383882d187df5 100644 (file)
@@ -1,5 +1,5 @@
 from posix.fcntl cimport pid_t
-from psycopg3.pq cimport libpq as impl
+from psycopg3_c cimport libpq as impl
 
 ctypedef char *(*conn_bytes_f) (const impl.PGconn *)
 ctypedef int(*conn_int_f) (const impl.PGconn *)
similarity index 99%
rename from psycopg3/pq/pq_cython.pyx
rename to psycopg3_c/psycopg3_c/pq_cython.pyx
index 903e332d68afb454882a298a2284b2fa7d04b3bf..a1daa8ee8a5d9f6fca4f43f4f9d248ad4974ab4b 100644 (file)
@@ -11,9 +11,8 @@ from cpython.bytes cimport PyBytes_AsString
 import logging
 from typing import List, Optional, Sequence, Tuple
 
-from psycopg3.pq cimport libpq as impl
-from psycopg3.pq.libpq cimport Oid
-from psycopg3.errors import OperationalError
+from psycopg3_c cimport libpq as impl
+from psycopg3_c.libpq cimport Oid
 
 from psycopg3.pq.misc import PGnotify, ConninfoOption, PQerror, PGresAttDesc
 from psycopg3.pq.misc import error_message
similarity index 98%
rename from psycopg3/transform.pyx
rename to psycopg3_c/psycopg3_c/transform.pyx
index 63205cb864711457296c06d400400bb5cce0c97d..28411b64f19f40c3bbff73bc8300ade8488fb4ce 100644 (file)
@@ -17,12 +17,11 @@ from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
 import codecs
 from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
 
-from psycopg3.pq cimport libpq
-from psycopg3.pq.pq_cython cimport PGresult
+from psycopg3_c cimport libpq
+from psycopg3_c.pq_cython cimport PGresult
 
 from psycopg3 import errors as e
 from psycopg3.pq.enums import Format
-# from psycopg3.types.oids import builtins, INVALID_OID
 
 TEXT_OID = 25
 
similarity index 96%
rename from psycopg3/types/numeric.pyx
rename to psycopg3_c/psycopg3_c/types/numeric.pyx
index 6192412e16da687f500b9a0284cad3e5fd1a71f8..642c98307498650b2fd3034caa8c3e876a58cf54 100644 (file)
@@ -5,7 +5,7 @@ Cython adapters for numeric types.
 # Copyright (C) 2020 The Psycopg Team
 
 from libc.stdint cimport *
-from psycopg3.types.endian cimport be16toh, be32toh, be64toh
+from psycopg3_c.endian cimport be16toh, be32toh, be64toh
 
 
 from cpython.long cimport (
similarity index 98%
rename from psycopg3/types/text.pyx
rename to psycopg3_c/psycopg3_c/types/text.pyx
index 27f0ef3afa068fe2bc63f51618ce94c1c55ee7b2..d3738fc0b9bc61d3bd932f7be9bcd1e1364846f7 100644 (file)
@@ -8,7 +8,7 @@ from cpython.bytes cimport PyBytes_FromStringAndSize
 from cpython.mem cimport PyMem_Malloc
 from cpython.object cimport PyObject
 from cpython.unicode cimport PyUnicode_DecodeUTF8
-from psycopg3.pq cimport libpq
+from psycopg3_c cimport libpq
 
 
 cdef struct TextContext:
diff --git a/psycopg3_c/psycopg3_c/version.py b/psycopg3_c/psycopg3_c/version.py
new file mode 100644 (file)
index 0000000..34a6c9b
--- /dev/null
@@ -0,0 +1,7 @@
+"""
+psycopg3-c distribution version file.
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+__version__ = "2.99.0"
diff --git a/psycopg3_c/pyproject.toml b/psycopg3_c/pyproject.toml
new file mode 100644 (file)
index 0000000..10e3548
--- /dev/null
@@ -0,0 +1,6 @@
+[build-system]
+requires = ["setuptools>=49.2.0", "wheel>=0.34.2", "Cython>=3.0a5"]
+build-backend = "setuptools.build_meta"
+
+[tool.black]
+line-length = 79
diff --git a/psycopg3_c/setup.cfg b/psycopg3_c/setup.cfg
new file mode 100644 (file)
index 0000000..90aed8d
--- /dev/null
@@ -0,0 +1,34 @@
+[metadata]
+name = psycopg3-c
+description = PostgreSQL database adapter for Python -- C optimisation distribution
+url = https://psycopg.org/psycopg3/
+author = Daniele Varrazzo
+author_email = daniele.varrazzo@gmail.com
+license = GNU Lesser General Public License v3 (LGPLv3)
+
+project_urls =
+    Homepage = https://psycopg.org/
+    Code = https://github.com/psycopg/psycopg3
+    Issue Tracker = https://github.com/psycopg/psycopg3/issues
+    Download = https://pypi.org/project/psycopg3-c/
+
+# TODO: classifiers
+classifiers =
+    Intended Audience :: Developers
+    Programming Language :: Python :: 3
+    License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
+    Topic :: Database
+    Topic :: Database :: Front-Ends
+    Topic :: Software Development
+    Topic :: Software Development :: Libraries :: Python Modules
+
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+license_file = LICENSE.txt
+
+[options]
+python_requires = >= 3.6
+setup_requires = Cython >= 3.0a5
+packages = find:
+zip_safe = False
+include_package_data = True
diff --git a/psycopg3_c/setup.py b/psycopg3_c/setup.py
new file mode 100644 (file)
index 0000000..30be456
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+"""
+PostgreSQL database adapter for Python - optimisation package
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+
+import os
+import re
+import subprocess as sp
+
+from setuptools import setup, Extension
+from distutils.command.build_ext import build_ext
+from distutils import log
+
+# Move to the directory of setup.py: executing this file from another location
+# (e.g. from the project root) will fail
+here = os.path.abspath(os.path.dirname(__file__))
+if os.path.abspath(os.getcwd()) != here:
+    os.chdir(here)
+
+with open("psycopg3_c/version.py") as f:
+    data = f.read()
+    m = re.search(r"""(?m)^__version__\s*=\s*['"]([^'"]+)['"]""", data)
+    if m is None:
+        raise Exception(f"cannot find version in {f.name}")
+    version = m.group(1)
+
+
+class psycopg3_build_ext(build_ext):
+    def finalize_options(self) -> None:
+        self._setup_ext_build()
+        super().finalize_options()
+
+    def _setup_ext_build(self) -> None:
+        cythonize = None
+
+        # In the sdist there are not .pyx, only c, so we don't need Cython
+        # Otherwise Cython is a requirement and is be used to compile pyx to c
+        if os.path.exists("psycopg3_c/_psycopg3.pyx"):
+            from Cython.Build import cythonize
+
+        # Add the include dir for the libpq.
+        try:
+            out = sp.run(
+                ["pg_config", "--includedir"], stdout=sp.PIPE, check=True
+            )
+        except Exception as e:
+            log.error("cannot build C module: %s", e)
+            raise
+
+        includedir = out.stdout.strip().decode("utf8")
+        for ext in self.distribution.ext_modules:
+            ext.include_dirs.append(includedir)
+
+        if cythonize is not None:
+            for ext in self.distribution.ext_modules:
+                ext.sources[0] = os.path.splitext(ext.sources[0])[0] + ".pyx"
+
+            self.distribution.ext_modules = cythonize(
+                self.distribution.ext_modules,
+                language_level=3,
+                annotate=False,  # enable to get an html view of the C module
+            )
+        else:
+            self.distribution.ext_modules = [pgext, pqext]
+
+
+# Some details missing, to be finished by psycopg3_build_ext.finalize_options
+pgext = Extension(
+    "psycopg3_c._psycopg3",
+    ["psycopg3_c/_psycopg3.c"],
+    libraries=["pq"],
+    include_dirs=[],
+)
+
+pqext = Extension(
+    "psycopg3_c.pq_cython",
+    ["psycopg3_c/pq_cython.c"],
+    libraries=["pq"],
+    include_dirs=[],
+)
+
+setup(
+    version=version,
+    # TODO: might use a range
+    install_requires=[f"psycopg3=={version}"],
+    ext_modules=[pgext, pqext],
+    cmdclass={"build_ext": psycopg3_build_ext},
+)
diff --git a/psycopg3_c/tox.ini b/psycopg3_c/tox.ini
new file mode 100644 (file)
index 0000000..2d4b731
--- /dev/null
@@ -0,0 +1,13 @@
+[tox]
+envlist = py{36,37,38}
+isolated_build = True
+
+[testenv]
+commands =
+    python ../psycopg3/setup.py develop
+    pytest ../tests {posargs}
+passenv = PG* PSYCOPG3_TEST_DSN PYTEST_ADDOPTS PSYCOPG3_IMPL
+deps =
+    pytest >= 5.3, < 6
+    pytest-asyncio >= 0.12.0, < 0.13
+    -e {toxinidir}/../psycopg3
index a8f43fefdf149ecbf2415952cba59074a3027744..372ef2d6099276f00b7ddb71df8d3e03de0aa567 100644 (file)
@@ -1,2 +1,11 @@
+[build-system]
+requires = ["setuptools>=49.2.0", "wheel>=0.34.2"]
+build-backend = "setuptools.build_meta"
+
 [tool.black]
 line-length = 79
+
+[tool.pytest.ini_options]
+testpaths=[
+    "tests",
+]
diff --git a/setup.py b/setup.py
deleted file mode 100644 (file)
index ab371e1..0000000
--- a/setup.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python3
-"""
-psycopg3 -- PostgreSQL database adapter for Python
-"""
-
-# Copyright (C) 2020 The Psycopg Team
-
-
-import re
-import os
-import subprocess as sp
-from setuptools import setup, find_packages, Extension
-from distutils.command.build_ext import build_ext
-from distutils import log
-
-try:
-    from Cython.Build import cythonize
-except ImportError:
-    cythonize = None
-
-# Grab the version without importing the module
-# or we will get import errors on install if prerequisites are still missing
-fn = os.path.join(os.path.dirname(__file__), "psycopg3/consts.py")
-with open(fn) as f:
-    m = re.search(r"""(?mi)^VERSION\s*=\s*["']+([^'"]+)["']+""", f.read())
-if m:
-    version = m.group(1)
-else:
-    raise ValueError("cannot find VERSION in the consts module")
-
-# Read the description from the README
-with open("README.rst") as f:
-    readme = f.read()
-
-# TODO: classifiers
-classifiers = """
-Intended Audience :: Developers
-Programming Language :: Python :: 3
-License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
-Topic :: Database
-Topic :: Database :: Front-Ends
-Topic :: Software Development
-Topic :: Software Development :: Libraries :: Python Modules
-"""
-
-
-class psycopg3_build_ext(build_ext):
-    def finalize_options(self) -> None:
-        self._setup_ext_build()
-        super().finalize_options()
-
-    def _setup_ext_build(self) -> None:
-        # Clear the dummy so if we can't build it's no drama
-        self.distribution.ext_modules = None
-
-        try:
-            from Cython.Build import cythonize
-        except ImportError:
-            log.warn("Cython is not available: the C module will not be built")
-            return
-
-        try:
-            out = sp.run(
-                ["pg_config", "--includedir"], stdout=sp.PIPE, check=True
-            )
-        except Exception as e:
-            log.warn("cannot build C module: %s", e)
-            return
-
-        includedir = out.stdout.strip().decode("utf8")
-
-        pgext = Extension(
-            "psycopg3._psycopg3",
-            ["psycopg3/_psycopg3.pyx"],
-            libraries=["pq"],
-            include_dirs=[includedir],
-        )
-        pqext = Extension(
-            "psycopg3.pq.pq_cython",
-            ["psycopg3/pq/pq_cython.pyx"],
-            libraries=["pq"],
-            include_dirs=[includedir],
-        )
-        self.distribution.ext_modules = cythonize(
-            [pgext, pqext],
-            language_level=3,
-            # annotate=True,  # enable to get an html view of the C module
-        )
-
-
-setup(
-    name="psycopg3",
-    description=readme.splitlines()[0],
-    long_description="\n".join(readme.splitlines()[2:]).lstrip(),
-    author="Daniele Varrazzo",
-    author_email="daniele.varrazzo@gmail.com",
-    url="https://psycopg.org/psycopg3/",
-    python_requires=">=3.6",
-    packages=find_packages(exclude=["tests"]),
-    classifiers=[x for x in classifiers.split("\n") if x],
-    setup_requires=["Cython>=3.0a2"],
-    install_requires=["typing_extensions"],
-    zip_safe=False,
-    include_package_data=True,
-    version=version,
-    project_urls={
-        "Homepage": "https://psycopg.org/",
-        "Code": "https://github.com/psycopg/psycopg3",
-        "Issue Tracker": "https://github.com/psycopg/psycopg3/issues",
-        "Download": "https://pypi.org/project/psycopg3/",
-    },
-    cmdclass={"build_ext": psycopg3_build_ext},
-    # hack to run build_ext. It will be replaced by real the stuff
-    ext_modules=[Extension("psycopg3.dummy", ["dummy.c"])],
-)
index 2eb890259767ec694b4593b902b945a75894bdfd..f17f16e0b170852b326dbbe5685b129f76fc6827 100644 (file)
@@ -1,8 +1,6 @@
 import os
 import pytest
 
-from psycopg3 import pq
-
 
 def pytest_addoption(parser):
     parser.addoption(
@@ -26,6 +24,8 @@ def dsn(request):
 @pytest.fixture
 def pgconn(dsn):
     """Return a PGconn connection open to `--test-dsn`."""
+    from psycopg3 import pq
+
     conn = pq.PGconn.connect(dsn.encode("utf8"))
     if conn.status != pq.ConnStatus.OK:
         pytest.fail(
index ae1e2a399f61ff265f864eaec43b9ed2e28eb7eb..fa0a566e8f81c4989cb667ffad2023d4930591a1 100644 (file)
@@ -2,10 +2,13 @@ import re
 import operator
 import pytest
 
-from psycopg3 import pq
-
 
 def pytest_report_header(config):
+    try:
+        from psycopg3 import pq
+    except ImportError:
+        return []
+
     return [
         f"libpq available: {pq.version()}",
         f"libpq wrapper implementation: {pq.__impl__}",
@@ -22,6 +25,8 @@ def pytest_configure(config):
 
 
 def pytest_runtest_setup(item):
+    from psycopg3 import pq
+
     for m in item.iter_markers(name="libpq"):
         check_libpq_version(pq.version(), m.args)
 
index 3753dde4fa3a865e843cd892637ac7ada9280502..e0d92096426ce8f0a686e35755214f87d15f2763 100644 (file)
@@ -194,7 +194,7 @@ def test_host(pgconn):
         pgconn.host
 
 
-# TODO: to implement in psycopg3.pq.pq_cython
+# TODO: to implement in pq_cython
 @pytest.mark.xfail
 @pytest.mark.libpq(">= 12")
 def test_hostaddr(pgconn):
index 509c9962ca47c254843d570684fbfeee2136b9fc..aafbdd27024d77c59ad4adb5ce1f56ce34449256 100644 (file)
@@ -99,6 +99,8 @@ t.join()
             f.write(module)
         env = dict(os.environ)
         env["PYTHONPATH"] = dir + os.pathsep + env.get("PYTHONPATH", "")
+        # TODO: debug this. Importing c module fails on travis in this scenario
+        env.pop("PSYCOPG3_IMPL", None)
         out = sp.check_output(
             [sys.executable, "-c", script], stderr=sp.STDOUT, env=env
         ).decode("utf8", "replace")
diff --git a/tox.ini b/tox.ini
index 72c7104442e5a3c9298cc296fe7b4a6d40ade162..db270ab32f46f7e07b3c4687a1e3d0e8e6a9cc66 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,44 +1,22 @@
-# Tox is nice, but rebuilding the environment every time is kinda slow.
-# If you want to install the test environments defined here into your current
-# virtualenv you can use:
-#
-#   pip install tox tox-current-env
-#   tox --print-deps-to-file /tmp/requirements.txt
-#   pip install -r /tmp/requirements.txt
-#
-# After which you can run the tests with:
-#
-#   tox --current-env -e ENV
-#
-# or just run manually the ``commands`` defined here.
-
 [tox]
-envlist = py{36,37,38}, black, flake8, mypy
-
-[testenv]
-# run setup.py develop to build the c extension in place.
-# if this doesn't happen, psycopg3 will be imported from the root directory
-# anyway rather than from the tox environment, because pytest adds the
-# root dir to the pythonpath. It sucks but I don't see a way around.
-commands =
-    python setup.py develop
-    pytest {posargs}
-passenv = PG* PSYCOPG3_TEST_DSN PYTEST_ADDOPTS PSYCOPG3_IMPL
-deps =
-    pytest >= 5.3, < 6
-    pytest-asyncio >= 0.12.0, < 0.13
+envlist = black, flake8, mypy
+isolated_build = True
 
 [testenv:black]
 commands = black --check --diff .
 deps = black
+skip_install = true
 
 [testenv:flake8]
 commands = flake8
 deps = flake8 >= 3.8, < 3.9
+skip_install = true
 
 [testenv:mypy]
 commands = mypy
 deps = mypy >= 0.782
+changedir = psycopg3
+skip_install = true
 
 [flake8]
 max-line-length = 85