From a86d51a891ac4cb63e2fe5f7ad0cf8713e4d899b Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Mon, 30 May 2022 09:32:25 +0200 Subject: [PATCH 01/62] Add pyproject.toml --- pyproject.toml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e69de29b From 35e067a20b8789550657f9dec1214ea07788f528 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Mon, 30 May 2022 10:02:45 +0200 Subject: [PATCH 02/62] Add basic project information to pyproject.toml --- pyproject.toml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index e69de29b..7f6890b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -0,0 +1,49 @@ +[build-system] +requires = [ + "poetry>=1.0.0", +] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "sqlalchemy_exasol" +version = "2.4.0" +description= "EXASOL dialect for SQLAlchemy" +readme = "README.rst" +license = "License :: OSI Approved :: BSD License" +authors = [ + "Exasol AG ", + "Blue Yonder GmbH", +] +classifiers=[ + "Development Status :: 5 - Production/Stable", + + "Operating System :: POSIX :: Linux", + + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Information Technology", + + "License :: OSI Approved :: BSD License", + + "Programming Language :: SQL", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + + "Topic :: Database", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Scientific/Engineering :: Information Analysis", +] +keywords = [ + "exasol", + "sql", + "sqlalchemy", + "data science", + "database", +] +repository = "https://github.com/exasol/sqlalchemy-exasol" +homepage = "https://www.exasol.com/" From 464f7bf7afe22d4e38aeab25e11b67e9f3ac0954 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Mon, 30 May 2022 11:37:34 +0200 Subject: [PATCH 03/62] Add dependencies to pyproject.toml --- pyproject.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7f6890b1..1f4a1182 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,3 +47,21 @@ keywords = [ ] repository = "https://github.com/exasol/sqlalchemy-exasol" homepage = "https://www.exasol.com/" + +[tool.poetry.dependencies] +python = ">=3.6" +SQLAlchemy = ">=1.3.24,<1.4" +pyodbc = ">=4.0.32" +turbodbc = {version = ">=3.3.0,<4", optional = true} + +[tool.poetry.dev-dependencies] +nox = ">=2022.1.7" +urlscan = ">=0.9.9" +pytest-json-report = ">=1.5.0" +# The excluded versions mirror the excluded versions of sqla 1.3.X. +# The limitation/issue pytest <6 is tracked in https://github.com/exasol/sqlalchemy-exasol/issues/144 +pytest = ">=3.1.0,!=3.9.1,!=3.9.2,<6" +pytest-cov = ">=2.7.0" + +[tool.poetry.extras] +turbodbc = ["turbodbc"] From e5d8348784cb386d9ebf3db7e8925260982fcad9 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Mon, 30 May 2022 12:55:24 +0200 Subject: [PATCH 04/62] Remove deprecated and unused configuration entries --- setup.cfg | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/setup.cfg b/setup.cfg index 3e519d5a..732fd123 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[egg_info] -#tag_build = dev - [tool:pytest] addopts= --tb native -v -r fxX python_files=test/*test_*.py @@ -11,10 +8,3 @@ filterwarnings = requirement_cls=sqlalchemy_exasol.requirements:Requirements profile_file=.profiles.txt -[db] -#specify default db connection string to run test against -#default=exa+pyodbc://USER:PWD@IP_RANGE:PORT/SCHEMA - -[bdist_wheel] -# Use this option if your package is pure-python -universal = 1 From ea3cd16870eced5d01cb45f78ed3b6de8a0530e3 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 31 May 2022 09:42:17 +0200 Subject: [PATCH 05/62] Update include list in pyproject.toml --- pyproject.toml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1f4a1182..9f83073e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,30 +7,25 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "sqlalchemy_exasol" version = "2.4.0" -description= "EXASOL dialect for SQLAlchemy" +description = "EXASOL dialect for SQLAlchemy" readme = "README.rst" license = "License :: OSI Approved :: BSD License" authors = [ "Exasol AG ", "Blue Yonder GmbH", ] -classifiers=[ +classifiers = [ "Development Status :: 5 - Production/Stable", - "Operating System :: POSIX :: Linux", - "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", - "License :: OSI Approved :: BSD License", - "Programming Language :: SQL", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", - "Topic :: Database", "Topic :: Software Development", "Topic :: Software Development :: Libraries", @@ -48,11 +43,20 @@ keywords = [ repository = "https://github.com/exasol/sqlalchemy-exasol" homepage = "https://www.exasol.com/" +include = [ + "sqlalchemy_exasol/_version.py", + "README.rst", + "CHANGES.md", + "LICENSE", +] +exclude = [] + + [tool.poetry.dependencies] python = ">=3.6" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" -turbodbc = {version = ">=3.3.0,<4", optional = true} +turbodbc = { version = ">=3.3.0,<4", optional = true } [tool.poetry.dev-dependencies] nox = ">=2022.1.7" @@ -65,3 +69,4 @@ pytest-cov = ">=2.7.0" [tool.poetry.extras] turbodbc = ["turbodbc"] + From 79508efed3f9bb79bf73c534369d79ff5c1349d9 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 31 May 2022 09:43:25 +0200 Subject: [PATCH 06/62] Add extension points required for sqlalchemy plugin(s) --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 9f83073e..577dafe9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,3 +70,6 @@ pytest-cov = ">=2.7.0" [tool.poetry.extras] turbodbc = ["turbodbc"] +[tool.poetry.plugins."sqlalchemy.dialects"] +"exa.pyodbc" = "sqlalchemy_exasol.pyodbc:EXADialect_pyodbc" +"exa.turbodbc" = "sqlalchemy_exasol.turbodbc:EXADialect_turbodbc" From 39b06e85ab959c0c2d2c4fc6d8f46e92b4d2d216 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 31 May 2022 11:22:14 +0200 Subject: [PATCH 07/62] Remove unused script --- versioneer.py | 809 -------------------------------------------------- 1 file changed, 809 deletions(-) delete mode 100644 versioneer.py diff --git a/versioneer.py b/versioneer.py deleted file mode 100644 index 112b2b9f..00000000 --- a/versioneer.py +++ /dev/null @@ -1,809 +0,0 @@ - -# Version: 0.10 - -""" -## Installation - -First, decide on values for the following configuration variables: - -* `versionfile_source`: - - A project-relative pathname into which the generated version strings should - be written. This is usually a `_version.py` next to your project's main - `__init__.py` file. If your project uses `src/myproject/__init__.py`, this - should be `src/myproject/_version.py`. This file should be checked in to - your VCS as usual: the copy created below by `setup.py versioneer` will - include code that parses expanded VCS keywords in generated tarballs. The - 'build' and 'sdist' commands will replace it with a copy that has just the - calculated version string. - -* `versionfile_build`: - - Like `versionfile_source`, but relative to the build directory instead of - the source directory. These will differ when your setup.py uses - 'package_dir='. If you have `package_dir={'myproject': 'src/myproject'}`, - then you will probably have `versionfile_build='myproject/_version.py'` and - `versionfile_source='src/myproject/_version.py'`. - -* `tag_prefix`: - - a string, like 'PROJECTNAME-', which appears at the start of all VCS tags. - If your tags look like 'myproject-1.2.0', then you should use - tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this - should be an empty string. - -* `parentdir_prefix`: - - a string, frequently the same as tag_prefix, which appears at the start of - all unpacked tarball filenames. If your tarball unpacks into - 'myproject-1.2.0', this should be 'myproject-'. - -This tool provides one script, named `versioneer-installer`. That script does -one thing: write a copy of `versioneer.py` into the current directory. - -To versioneer-enable your project: - -* 1: Run `versioneer-installer` to copy `versioneer.py` into the top of your - source tree. - -* 2: add the following lines to the top of your `setup.py`, with the - configuration values you decided earlier: - - import versioneer - versioneer.versionfile_source = 'src/myproject/_version.py' - versioneer.versionfile_build = 'myproject/_version.py' - versioneer.tag_prefix = '' # tags are like 1.2.0 - versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0' - -* 3: add the following arguments to the setup() call in your setup.py: - - version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), - -* 4: now run `setup.py versioneer`, which will create `_version.py`, and - will modify your `__init__.py` to define `__version__` (by calling a - function from `_version.py`). It will also modify your `MANIFEST.in` to - include both `versioneer.py` and the generated `_version.py` in sdist - tarballs. - -* 5: commit these changes to your VCS. To make sure you won't forget, - `setup.py versioneer` will mark everything it touched for addition. - -## Post-Installation Usage - -Once established, all uses of your tree from a VCS checkout should get the -current version string. All generated tarballs should include an embedded -version string (so users who unpack them will not need a VCS tool installed). - -If you distribute your project through PyPI, then the release process should -boil down to two steps: - -* 1: git tag 1.0 -* 2: python setup.py register sdist upload - -If you distribute it through github (i.e. users use github to generate -tarballs with `git archive`), the process is: - -* 1: git tag 1.0 -* 2: git push; git push --tags - -Currently, all version strings must be based upon a tag. Versioneer will -report "unknown" until your tree has at least one tag in its history. This -restriction will be fixed eventually (see issue #12). - -## Version-String Flavors - -Code which uses Versioneer can learn about its version string at runtime by -importing `_version` from your main `__init__.py` file and running the -`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can -import the top-level `versioneer.py` and run `get_versions()`. - -Both functions return a dictionary with different keys for different flavors -of the version string: - -* `['version']`: condensed tag+distance+shortid+dirty identifier. For git, - this uses the output of `git describe --tags --dirty --always` but strips - the tag_prefix. For example "0.11-2-g1076c97-dirty" indicates that the tree - is like the "1076c97" commit but has uncommitted changes ("-dirty"), and - that this commit is two revisions ("-2-") beyond the "0.11" tag. For - released software (exactly equal to a known tag), the identifier will only - contain the stripped tag, e.g. "0.11". - -* `['full']`: detailed revision identifier. For Git, this is the full SHA1 - commit id, followed by "-dirty" if the tree contains uncommitted changes, - e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac-dirty". - -Some variants are more useful than others. Including `full` in a bug report -should allow developers to reconstruct the exact code being tested (or -indicate the presence of local changes that should be shared with the -developers). `version` is suitable for display in an "about" box or a CLI -`--version` output: it can be easily compared against release notes and lists -of bugs fixed in various releases. - -In the future, this will also include a -[PEP-0440](http://legacy.python.org/dev/peps/pep-0440/) -compatible flavor -(e.g. `1.2.post0.dev123`). This loses a lot of information (and has no room -for a hash-based revision id), but is safe to use in a `setup.py` -"`version=`" argument. It also enables tools like *pip* to compare version -strings and evaluate compatibility constraint declarations. - -The `setup.py versioneer` command adds the following text to your -`__init__.py` to place a basic version in `YOURPROJECT.__version__`: - - from ._version import get_versions - __version = get_versions()['version'] - del get_versions - -## Updating Versioneer - -To upgrade your project to a new release of Versioneer, do the following: - -* install the new Versioneer (`pip install -U versioneer` or equivalent) -* re-run `versioneer-installer` in your source tree to replace `versioneer.py` -* edit `setup.py`, if necessary, to include any new configuration settings indicated by the release notes -* re-run `setup.py versioneer` to replace `SRC/_version.py` -* commit any changed files - -## Future Directions - -This tool is designed to make it easily extended to other version-control -systems: all VCS-specific components are in separate directories like -src/git/ . The top-level `versioneer.py` script is assembled from these -components by running make-versioneer.py . In the future, make-versioneer.py -will take a VCS name as an argument, and will construct a version of -`versioneer.py` that is specific to the given VCS. It might also take the -configuration arguments that are currently provided manually during -installation by editing setup.py . Alternatively, it might go the other -direction and include code from all supported VCS systems, reducing the -number of intermediate scripts. - - -## License - -To make Versioneer easier to embed, all its code is hereby released into the -public domain. The `_version.py` that it creates is also in the public -domain. - -""" - -import os, sys, re -from distutils.core import Command -from distutils.command.sdist import sdist as _sdist -from distutils.command.build import build as _build - -versionfile_source = None -versionfile_build = None -tag_prefix = None -parentdir_prefix = None - -VCS = "git" - - -LONG_VERSION_PY = ''' -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (build by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.10 (https://github.com/warner/python-versioneer) - -# these strings will be replaced by git during git-archive -git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" -git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" - - -import subprocess -import sys -import errno - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False): - assert isinstance(commands, list) - p = None - for c in commands: - try: - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %%s" %% args[0]) - print(e) - return None - else: - if verbose: - print("unable to find command, tried %%s" %% (commands,)) - return None - stdout = p.communicate()[0].strip() - if sys.version >= '3': - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %%s (error)" %% args[0]) - return None - return stdout - - -import sys -import re -import os.path - -def get_expanded_variables(versionfile_abs): - # the code embedded in _version.py can just fetch the value of these - # variables. When used from setup.py, we don't want to import - # _version.py, so we do it with a regexp instead. This function is not - # used from _version.py. - variables = {} - try: - f = open(versionfile_abs,"r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["full"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return variables - -def versions_from_expanded_variables(variables, tag_prefix, verbose=False): - refnames = variables["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("variables are unexpanded, not using") - return {} # unexpanded, so not in an unpacked git-archive tarball - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %%d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%%s', no digits" %% ",".join(refs-tags)) - if verbose: - print("likely tags: %%s" %% ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %%s" %% r) - return { "version": r, - "full": variables["full"].strip() } - # no suitable tags, so we use the full revision id - if verbose: - print("no suitable tags, using full revision id") - return { "version": variables["full"].strip(), - "full": variables["full"].strip() } - -def versions_from_vcs(tag_prefix, root, verbose=False): - # this runs 'git' from the root of the source tree. This only gets called - # if the git-archive 'subst' variables were *not* expanded, and - # _version.py hasn't already been rewritten with a short version string, - # meaning we're inside a checked out source tree. - - if not os.path.exists(os.path.join(root, ".git")): - if verbose: - print("no .git in %%s" %% root) - return {} - - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"], - cwd=root) - if stdout is None: - return {} - if not stdout.startswith(tag_prefix): - if verbose: - print("tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix)) - return {} - tag = stdout[len(tag_prefix):] - stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if stdout is None: - return {} - full = stdout.strip() - if tag.endswith("-dirty"): - full += "-dirty" - return {"version": tag, "full": full} - - -def versions_from_parentdir(parentdir_prefix, root, verbose=False): - # Source tarballs conventionally unpack into a directory that includes - # both the project name and a version string. - dirname = os.path.basename(root) - if not dirname.startswith(parentdir_prefix): - if verbose: - print("guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %% - (root, dirname, parentdir_prefix)) - return None - return {"version": dirname[len(parentdir_prefix):], "full": ""} - -tag_prefix = "%(TAG_PREFIX)s" -parentdir_prefix = "%(PARENTDIR_PREFIX)s" -versionfile_source = "%(VERSIONFILE_SOURCE)s" - -def get_versions(default={"version": "unknown", "full": ""}, verbose=False): - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded variables. - - variables = { "refnames": git_refnames, "full": git_full } - ver = versions_from_expanded_variables(variables, tag_prefix, verbose) - if ver: - return ver - - try: - root = os.path.abspath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - except NameError: - return default - - return (versions_from_vcs(tag_prefix, root, verbose) - or versions_from_parentdir(parentdir_prefix, root, verbose) - or default) - -''' - - -import subprocess -import sys -import errno - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False): - assert isinstance(commands, list) - p = None - for c in commands: - try: - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % args[0]) - print(e) - return None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None - stdout = p.communicate()[0].strip() - if sys.version >= '3': - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % args[0]) - return None - return stdout - - -import sys -import re -import os.path - -def get_expanded_variables(versionfile_abs): - # the code embedded in _version.py can just fetch the value of these - # variables. When used from setup.py, we don't want to import - # _version.py, so we do it with a regexp instead. This function is not - # used from _version.py. - variables = {} - try: - f = open(versionfile_abs,"r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["full"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return variables - -def versions_from_expanded_variables(variables, tag_prefix, verbose=False): - refnames = variables["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("variables are unexpanded, not using") - return {} # unexpanded, so not in an unpacked git-archive tarball - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%s', no digits" % ",".join(refs-tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return { "version": r, - "full": variables["full"].strip() } - # no suitable tags, so we use the full revision id - if verbose: - print("no suitable tags, using full revision id") - return { "version": variables["full"].strip(), - "full": variables["full"].strip() } - -def versions_from_vcs(tag_prefix, root, verbose=False): - # this runs 'git' from the root of the source tree. This only gets called - # if the git-archive 'subst' variables were *not* expanded, and - # _version.py hasn't already been rewritten with a short version string, - # meaning we're inside a checked out source tree. - - if not os.path.exists(os.path.join(root, ".git")): - if verbose: - print("no .git in %s" % root) - return {} - - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"], - cwd=root) - if stdout is None: - return {} - if not stdout.startswith(tag_prefix): - if verbose: - print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) - return {} - tag = stdout[len(tag_prefix):] - stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if stdout is None: - return {} - full = stdout.strip() - if tag.endswith("-dirty"): - full += "-dirty" - return {"version": tag, "full": full} - - -def versions_from_parentdir(parentdir_prefix, root, verbose=False): - # Source tarballs conventionally unpack into a directory that includes - # both the project name and a version string. - dirname = os.path.basename(root) - if not dirname.startswith(parentdir_prefix): - if verbose: - print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % - (root, dirname, parentdir_prefix)) - return None - return {"version": dirname[len(parentdir_prefix):], "full": ""} -import os.path -import sys - -# os.path.relpath only appeared in Python-2.6 . Define it here for 2.5. -def os_path_relpath(path, start=os.path.curdir): - """Return a relative version of a path""" - - if not path: - raise ValueError("no path specified") - - start_list = [x for x in os.path.abspath(start).split(os.path.sep) if x] - path_list = [x for x in os.path.abspath(path).split(os.path.sep) if x] - - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - - rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return os.path.curdir - return os.path.join(*rel_list) - -def do_vcs_install(manifest_in, versionfile_source, ipy): - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - files = [manifest_in, versionfile_source, ipy] - try: - me = __file__ - if me.endswith(".pyc") or me.endswith(".pyo"): - me = os.path.splitext(me)[0] + ".py" - versioneer_file = os_path_relpath(me) - except NameError: - versioneer_file = "versioneer.py" - files.append(versioneer_file) - present = False - try: - f = open(".gitattributes", "r") - for line in f.readlines(): - if line.strip().startswith(versionfile_source): - if "export-subst" in line.strip().split()[1:]: - present = True - f.close() - except EnvironmentError: - pass - if not present: - f = open(".gitattributes", "a+") - f.write("%s export-subst\n" % versionfile_source) - f.close() - files.append(".gitattributes") - run_command(GITS, ["add", "--"] + files) - -SHORT_VERSION_PY = """ -# This file was generated by 'versioneer.py' (0.10) from -# revision-control system data, or from the parent directory name of an -# unpacked source archive. Distribution tarballs contain a pre-generated copy -# of this file. - -version_version = '%(version)s' -version_full = '%(full)s' -def get_versions(default={}, verbose=False): - return {'version': version_version, 'full': version_full} - -""" - -DEFAULT = {"version": "unknown", "full": "unknown"} - -def versions_from_file(filename): - versions = {} - try: - f = open(filename) - except EnvironmentError: - return versions - for line in f.readlines(): - mo = re.match("version_version = '([^']+)'", line) - if mo: - versions["version"] = mo.group(1) - mo = re.match("version_full = '([^']+)'", line) - if mo: - versions["full"] = mo.group(1) - f.close() - return versions - -def write_to_version_file(filename, versions): - f = open(filename, "w") - f.write(SHORT_VERSION_PY % versions) - f.close() - print("set %s to '%s'" % (filename, versions["version"])) - -def get_root(): - try: - return os.path.dirname(os.path.abspath(__file__)) - except NameError: - return os.path.dirname(os.path.abspath(sys.argv[0])) - -def get_versions(default=DEFAULT, verbose=False): - # returns dict with two keys: 'version' and 'full' - assert versionfile_source is not None, "please set versioneer.versionfile_source" - assert tag_prefix is not None, "please set versioneer.tag_prefix" - assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix" - # I am in versioneer.py, which must live at the top of the source tree, - # which we use to compute the root directory. py2exe/bbfreeze/non-CPython - # don't have __file__, in which case we fall back to sys.argv[0] (which - # ought to be the setup.py script). We prefer __file__ since that's more - # robust in cases where setup.py was invoked in some weird way (e.g. pip) - root = get_root() - versionfile_abs = os.path.join(root, versionfile_source) - - # extract version from first of _version.py, 'git describe', parentdir. - # This is meant to work for developers using a source checkout, for users - # of a tarball created by 'setup.py sdist', and for users of a - # tarball/zipball created by 'git archive' or github's download-from-tag - # feature. - - variables = get_expanded_variables(versionfile_abs) - if variables: - ver = versions_from_expanded_variables(variables, tag_prefix) - if ver: - if verbose: print("got version from expanded variable %s" % ver) - return ver - - ver = versions_from_file(versionfile_abs) - if ver: - if verbose: print("got version from file %s %s" % (versionfile_abs,ver)) - return ver - - ver = versions_from_vcs(tag_prefix, root, verbose) - if ver: - if verbose: print("got version from git %s" % ver) - return ver - - ver = versions_from_parentdir(parentdir_prefix, root, verbose) - if ver: - if verbose: print("got version from parentdir %s" % ver) - return ver - - if verbose: print("got version from default %s" % ver) - return default - -def get_version(verbose=False): - return get_versions(verbose=verbose)["version"] - -class cmd_version(Command): - description = "report generated version string" - user_options = [] - boolean_options = [] - def initialize_options(self): - pass - def finalize_options(self): - pass - def run(self): - ver = get_version(verbose=True) - print("Version is currently: %s" % ver) - - -class cmd_build(_build): - def run(self): - versions = get_versions(verbose=True) - _build.run(self) - # now locate _version.py in the new build/ directory and replace it - # with an updated value - target_versionfile = os.path.join(self.build_lib, versionfile_build) - print("UPDATING %s" % target_versionfile) - os.unlink(target_versionfile) - f = open(target_versionfile, "w") - f.write(SHORT_VERSION_PY % versions) - f.close() - -if 'cx_Freeze' in sys.modules: # cx_freeze enabled? - from cx_Freeze.dist import build_exe as _build_exe - - class cmd_build_exe(_build_exe): - def run(self): - versions = get_versions(verbose=True) - target_versionfile = versionfile_source - print("UPDATING %s" % target_versionfile) - os.unlink(target_versionfile) - f = open(target_versionfile, "w") - f.write(SHORT_VERSION_PY % versions) - f.close() - _build_exe.run(self) - os.unlink(target_versionfile) - f = open(versionfile_source, "w") - f.write(LONG_VERSION_PY % {"DOLLAR": "$", - "TAG_PREFIX": tag_prefix, - "PARENTDIR_PREFIX": parentdir_prefix, - "VERSIONFILE_SOURCE": versionfile_source, - }) - f.close() - -class cmd_sdist(_sdist): - def run(self): - versions = get_versions(verbose=True) - self._versioneer_generated_versions = versions - # unless we update this, the command will keep using the old version - self.distribution.metadata.version = versions["version"] - return _sdist.run(self) - - def make_release_tree(self, base_dir, files): - _sdist.make_release_tree(self, base_dir, files) - # now locate _version.py in the new base_dir directory (remembering - # that it may be a hardlink) and replace it with an updated value - target_versionfile = os.path.join(base_dir, versionfile_source) - print("UPDATING %s" % target_versionfile) - os.unlink(target_versionfile) - f = open(target_versionfile, "w") - f.write(SHORT_VERSION_PY % self._versioneer_generated_versions) - f.close() - -INIT_PY_SNIPPET = """ -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions -""" - -class cmd_update_files(Command): - description = "install/upgrade Versioneer files: __init__.py SRC/_version.py" - user_options = [] - boolean_options = [] - def initialize_options(self): - pass - def finalize_options(self): - pass - def run(self): - print(" creating %s" % versionfile_source) - f = open(versionfile_source, "w") - f.write(LONG_VERSION_PY % {"DOLLAR": "$", - "TAG_PREFIX": tag_prefix, - "PARENTDIR_PREFIX": parentdir_prefix, - "VERSIONFILE_SOURCE": versionfile_source, - }) - f.close() - - ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py") - try: - old = open(ipy, "r").read() - except EnvironmentError: - old = "" - if INIT_PY_SNIPPET not in old: - print(" appending to %s" % ipy) - f = open(ipy, "a") - f.write(INIT_PY_SNIPPET) - f.close() - else: - print(" %s unmodified" % ipy) - - # Make sure both the top-level "versioneer.py" and versionfile_source - # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so - # they'll be copied into source distributions. Pip won't be able to - # install the package without this. - manifest_in = os.path.join(get_root(), "MANIFEST.in") - simple_includes = set() - try: - for line in open(manifest_in, "r").readlines(): - if line.startswith("include "): - for include in line.split()[1:]: - simple_includes.add(include) - except EnvironmentError: - pass - # That doesn't cover everything MANIFEST.in can do - # (http://docs.python.org/2/distutils/sourcedist.html#commands), so - # it might give some false negatives. Appending redundant 'include' - # lines is safe, though. - if "versioneer.py" not in simple_includes: - print(" appending 'versioneer.py' to MANIFEST.in") - f = open(manifest_in, "a") - f.write("include versioneer.py\n") - f.close() - else: - print(" 'versioneer.py' already in MANIFEST.in") - if versionfile_source not in simple_includes: - print(" appending versionfile_source ('%s') to MANIFEST.in" % - versionfile_source) - f = open(manifest_in, "a") - f.write("include %s\n" % versionfile_source) - f.close() - else: - print(" versionfile_source already in MANIFEST.in") - - # Make VCS-specific changes. For git, this means creating/changing - # .gitattributes to mark _version.py for export-time keyword - # substitution. - do_vcs_install(manifest_in, versionfile_source, ipy) - -def get_cmdclass(): - cmds = {'version': cmd_version, - 'versioneer': cmd_update_files, - 'build': cmd_build, - 'sdist': cmd_sdist, - } - if 'cx_Freeze' in sys.modules: # cx_freeze enabled? - cmds['build_exe'] = cmd_build_exe - del cmds['build'] - - return cmds From 5de6bbe8e785ce3ee8eb4bd6fa0d174b3ded0df2 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 31 May 2022 16:05:58 +0200 Subject: [PATCH 08/62] Add sync support for project.toml based version --- .pre-commit-config.yaml | 11 +++ pyproject.toml | 4 +- scripts/version_check.py | 134 +++++++++++++++++++++++++++++++++++ sqlalchemy_exasol/version.py | 9 +++ 4 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 scripts/version_check.py create mode 100644 sqlalchemy_exasol/version.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..f097022a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,11 @@ +default_stages: [commit] +repos: +- repo: local + hooks: + + - id: version-check + name: Check if version(s) are in sync + always_run: true + verbose: true + language: system + entry: python scripts/version_check.py sqlalchemy_exasol/version.py \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 577dafe9..17d88b65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,6 @@ repository = "https://github.com/exasol/sqlalchemy-exasol" homepage = "https://www.exasol.com/" include = [ - "sqlalchemy_exasol/_version.py", "README.rst", "CHANGES.md", "LICENSE", @@ -53,7 +52,7 @@ exclude = [] [tool.poetry.dependencies] -python = ">=3.6" +python = ">=3.7,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" turbodbc = { version = ">=3.3.0,<4", optional = true } @@ -66,6 +65,7 @@ pytest-json-report = ">=1.5.0" # The limitation/issue pytest <6 is tracked in https://github.com/exasol/sqlalchemy-exasol/issues/144 pytest = ">=3.1.0,!=3.9.1,!=3.9.2,<6" pytest-cov = ">=2.7.0" +pre-commit = "^2.19.0" [tool.poetry.extras] turbodbc = ["turbodbc"] diff --git a/scripts/version_check.py b/scripts/version_check.py new file mode 100644 index 00000000..a51b3f59 --- /dev/null +++ b/scripts/version_check.py @@ -0,0 +1,134 @@ +import argparse +import subprocess +import sys +from collections import namedtuple +from inspect import cleandoc +from pathlib import Path +from shutil import which + +Version = namedtuple("Version", ["major", "minor", "patch"]) + +_SUCCESS = 0 +_FAILURE = 1 + +# fmt: off +_VERSION_MODULE_TEMPLATE = cleandoc(''' +# ATTENTION: +# This file is generated, do not edit this file manually! +# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. + +MAJOR = {major} +MINOR = {minor} +PATCH = {patch} + +VERSION = f"{{MAJOR}}.{{MINOR}}.{{PATCH}}" +''') + "\n" +# fmt: on + + +def version_from_string(s): + """Converts a version string of the following format major.minor.patch to a version object""" + major, minor, patch = [int(number, base=0) for number in s.split(".")] + return Version(major, minor, patch) + + +class CommitHookError(Exception): + """Indicates that this commit hook encountered an error""" + + +def version_from_python_module(path): + """Retrieve version information from the `version` module""" + with open(path, "r") as file: + _locals, _globals = {}, {} + exec(file.read(), _locals, _globals) + + try: + version = _globals["VERSION"] + except KeyError as ex: + raise CommitHookError("Couldn't find version within module") from ex + + return version_from_string(version) + + +def version_from_poetry(): + poetry = which("poetry") + if not poetry: + raise CommitHookError("Couldn't find poetry executable") + + result = subprocess.run( + [poetry, "version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + version = result.stdout.decode().split()[1] + return version_from_string(version) + + +def write_version_module(version, path, exists_ok=True): + version_file = Path(path) + if version_file.exists() and not exists_ok: + raise CommitHookError(f"Version file [{version_file}] already exists.") + version_file.unlink(missing_ok=True) + with open(version_file, "w") as f: + f.write( + _VERSION_MODULE_TEMPLATE.format( + major=version.major, minor=version.minor, patch=version.patch + ) + ) + + +def _create_parser(): + parser = argparse.ArgumentParser() + parser.add_argument("version_module", help="Path to version module") + parser.add_argument("files", nargs="*") + parser.add_argument( + "-d", + "--debug", + action="store_true", + default=False, + help="enabled debug mode for execution.", + ) + parser.add_argument( + "-c", + "--check", + action="store_true", + default=False, + help="check instead of update/fix.", + ) + return parser + + +def _main_debug(args): + module_version = version_from_python_module(args.version_module) + poetry_version = version_from_poetry() + + def are_versions_equal(lhs, rhs): + return ( + lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch + ) + + if not are_versions_equal(module_version, poetry_version): + print( + f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!" + ) + if not args.check: + write_version_module(poetry_version, args.version_module) + return _FAILURE + return _SUCCESS + + +def _main(args): + try: + return _main_debug(args) + except Exception as ex: + print(f"Error while executing program, details: {ex}", file=sys.stderr) + return _FAILURE + + +def main(argv=None): + parser = _create_parser() + args = parser.parse_args() + entry_point = _main if not args.debug else _main_debug + return entry_point(args) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/sqlalchemy_exasol/version.py b/sqlalchemy_exasol/version.py new file mode 100644 index 00000000..38ddb72b --- /dev/null +++ b/sqlalchemy_exasol/version.py @@ -0,0 +1,9 @@ +# ATTENTION: +# This file is generated, do not edit this file manually! +# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. + +MAJOR = 2 +MINOR = 4 +PATCH = 0 + +VERSION = f"{MAJOR}.{MINOR}.{PATCH}" From db10601d59ecbbba2a9c9a7351c542aecd68d6e3 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 09:34:10 +0200 Subject: [PATCH 09/62] Add version check to ci/verifier action --- noxfile.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index dee89fd1..1fe70229 100644 --- a/noxfile.py +++ b/noxfile.py @@ -83,17 +83,28 @@ def temporary_odbc_config(config): @contextmanager def odbcconfig(): with temporary_odbc_config( - ODBCINST_INI_TEMPLATE.format(driver=Settings.ODBC_DRIVER) + ODBCINST_INI_TEMPLATE.format(driver=Settings.ODBC_DRIVER) ) as cfg: env_vars = {"ODBCSYSINI": f"{cfg.parent.resolve()}"} with environment(env_vars) as env: yield cfg, env +@nox.session(name="check-version", reuse_venv=True) +def check_version(session): + session.run( + "python", + f"{SCRIPTS / 'version_check.py'}", + "--check", + f"{PROJECT_ROOT / 'sqlalchemy_exasol' / 'version.py'}", + ) + + @nox.session @nox.parametrize("connector", Settings.CONNECTORS) def verify(session, connector): """Prepare and run all available tests""" + session.notify(find_session_runner(session, "check-version")) session.notify(find_session_runner(session, "db-start")) session.notify( find_session_runner(session, f"integration(connector='{connector}')") From 96b9c70982862d55d4c769638cb7ce5c9bd03f17 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 10:49:16 +0200 Subject: [PATCH 10/62] Add justification why the pytest config still is part of setup.cfg --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index 732fd123..0b65f66f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,6 @@ +# pyproject.toml based configuration is supported starting with pytest >= 6 +# see https://github.com/exasol/sqlalchemy-exasol/issues/144 +supports pyproject.toml [tool:pytest] addopts= --tb native -v -r fxX python_files=test/*test_*.py From 474b898e357c57e1990be89ed6e14d0243b428a4 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 10:51:23 +0200 Subject: [PATCH 11/62] Remove condaforge reference in README Conda forge is not maintained anymore. --- README.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.rst b/README.rst index 6abd406e..f69f3b4f 100644 --- a/README.rst +++ b/README.rst @@ -7,9 +7,6 @@ SQLAlchemy Dialect for EXASOL DB .. image:: https://img.shields.io/pypi/v/sqlalchemy_exasol :target: https://pypi.org/project/sqlalchemy-exasol/ :alt: PyPI Version -.. image:: https://img.shields.io/conda/vn/conda-forge/sqlalchemy_exasol.svg - :target: https://anaconda.org/conda-forge/sqlalchemy_exasol - :alt: Conda Version This is an SQLAlchemy dialect for the EXASOL database. From 286305a2ea323daca56cfbe487397060c733dff9 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 10:53:44 +0200 Subject: [PATCH 12/62] Fix error in setup.cfg --- setup.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 0b65f66f..f2400ca2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,5 @@ # pyproject.toml based configuration is supported starting with pytest >= 6 # see https://github.com/exasol/sqlalchemy-exasol/issues/144 -supports pyproject.toml [tool:pytest] addopts= --tb native -v -r fxX python_files=test/*test_*.py From 4ea0d5eed15d45876616c4c171b3eea9162fd023 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 10:54:48 +0200 Subject: [PATCH 13/62] Replace version information mechansim For now the version and iformation will be updated using a git hook and nox target. When the project is upgraded to 3.8 we should replace this mechanism by the use of importlib.metadata. see also: * https://github.com/exasol/sqlalchemy-exasol/pull/145#discussion_r885733975 * https://github.com/python-poetry/poetry/pull/2366#issuecomment-652418094 * https://github.com/exasol/sqlalchemy-exasol/issues/135#issuecomment-1143186610 --- sqlalchemy_exasol/__init__.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sqlalchemy_exasol/__init__.py b/sqlalchemy_exasol/__init__.py index cec05359..6dcb961f 100644 --- a/sqlalchemy_exasol/__init__.py +++ b/sqlalchemy_exasol/__init__.py @@ -1,9 +1,6 @@ -try: - from ._version import version as __version__ -except ImportError: # pragma: no cover - __version__ = "unknown" - +from version import VERSION from sqlalchemy_exasol import base, pyodbc +__version__ = VERSION # default dialect base.dialect = pyodbc.dialect From 6bf3af52c7fdf77284921355ee94754ae63d4873 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 10:59:02 +0200 Subject: [PATCH 14/62] Add poetry lock file --- poetry.lock | 723 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 723 insertions(+) create mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..b1c836af --- /dev/null +++ b/poetry.lock @@ -0,0 +1,723 @@ +[[package]] +name = "argcomplete" +version = "1.12.3" +description = "Bash tab completion for argparse" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +importlib-metadata = {version = ">=0.23,<5", markers = "python_version == \"3.7\""} + +[package.extras] +test = ["coverage", "flake8", "pexpect", "wheel"] + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "cfgv" +version = "3.3.1" +description = "Validate configuration and produce human readable error messages." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "colorlog" +version = "6.6.0" +description = "Add colours to the output of Python's logging module." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + +[[package]] +name = "coverage" +version = "6.4" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "distlib" +version = "0.3.4" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "filelock" +version = "3.7.1" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] + +[[package]] +name = "identify" +version = "2.5.1" +description = "File identification library for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "importlib-metadata" +version = "4.11.4" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] + +[[package]] +name = "more-itertools" +version = "8.13.0" +description = "More routines for operating on iterables, beyond itertools" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "nodeenv" +version = "1.6.0" +description = "Node.js virtual environment builder" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "nox" +version = "2022.1.7" +description = "Flexible test automation." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +argcomplete = ">=1.9.4,<2.0" +colorlog = ">=2.6.1,<7.0.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +packaging = ">=20.9" +py = ">=1.4.0,<2.0.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} +virtualenv = ">=14.0.0" + +[package.extras] +tox_to_nox = ["jinja2", "tox"] + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "platformdirs" +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] + +[[package]] +name = "pluggy" +version = "0.13.1" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[package.extras] +dev = ["pre-commit", "tox"] + +[[package]] +name = "pre-commit" +version = "2.19.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pybind11" +version = "2.9.2" +description = "Seamless operability between C++11 and Python" +category = "main" +optional = true +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.extras] +global = ["pybind11-global (==2.9.2)"] + +[[package]] +name = "pyodbc" +version = "4.0.32" +description = "DB API Module for ODBC" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "dev" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pytest" +version = "5.4.3" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=17.4.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +more-itertools = ">=4.0.0" +packaging = "*" +pluggy = ">=0.12,<1.0" +py = ">=1.5.0" +wcwidth = "*" + +[package.extras] +checkqa-mypy = ["mypy (==v0.761)"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-json-report" +version = "1.5.0" +description = "A pytest plugin to report test results as JSON files" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +pytest = ">=3.8.0" +pytest-metadata = "*" + +[[package]] +name = "pytest-metadata" +version = "1.11.0" +description = "pytest plugin for test session metadata" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +pytest = ">=2.9.0" + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "sqlalchemy" +version = "1.3.24" +description = "Database Abstraction Library" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +mssql = ["pyodbc"] +mssql_pymssql = ["pymssql"] +mssql_pyodbc = ["pyodbc"] +mysql = ["mysqlclient"] +oracle = ["cx-oracle"] +postgresql = ["psycopg2"] +postgresql_pg8000 = ["pg8000 (<1.16.6)"] +postgresql_psycopg2binary = ["psycopg2-binary"] +postgresql_psycopg2cffi = ["psycopg2cffi"] +pymysql = ["pymysql (<1)", "pymysql"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "turbodbc" +version = "3.3.0" +description = "turbodbc is a Python DB API 2.0 compatible ODBC driver" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +pybind11 = ">=2.2.0" +six = "*" + +[package.extras] +arrow = ["pyarrow (>=0.12,<0.16)"] +numpy = ["numpy (>=1.14.0)"] + +[[package]] +name = "typing-extensions" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urlscan" +version = "0.9.9" +description = "View/select the URLs in an email message or file" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +urwid = ">=1.2.1" + +[[package]] +name = "urwid" +version = "2.1.2" +description = "A full-featured console (xterm et al.) user interface library" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "virtualenv" +version = "20.14.1" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +distlib = ">=0.3.1,<1" +filelock = ">=3.2,<4" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +platformdirs = ">=2,<3" +six = ">=1.9.0,<2" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "zipp" +version = "3.8.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + +[extras] +turbodbc = ["turbodbc"] + +[metadata] +lock-version = "1.1" +python-versions = ">=3.7,<4.0" +content-hash = "fde39bfa9f47038eec3cedef28d4fcad8c722e31865f1a4ecae9026d1b843b52" + +[metadata.files] +argcomplete = [ + {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, + {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +colorlog = [ + {file = "colorlog-6.6.0-py2.py3-none-any.whl", hash = "sha256:351c51e866c86c3217f08e4b067a7974a678be78f07f85fc2d55b8babde6d94e"}, + {file = "colorlog-6.6.0.tar.gz", hash = "sha256:344f73204009e4c83c5b6beb00b3c45dc70fcdae3c80db919e0a4171d006fde8"}, +] +coverage = [ + {file = "coverage-6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50ed480b798febce113709846b11f5d5ed1e529c88d8ae92f707806c50297abf"}, + {file = "coverage-6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26f8f92699756cb7af2b30720de0c5bb8d028e923a95b6d0c891088025a1ac8f"}, + {file = "coverage-6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60c2147921da7f4d2d04f570e1838db32b95c5509d248f3fe6417e91437eaf41"}, + {file = "coverage-6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:750e13834b597eeb8ae6e72aa58d1d831b96beec5ad1d04479ae3772373a8088"}, + {file = "coverage-6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af5b9ee0fc146e907aa0f5fb858c3b3da9199d78b7bb2c9973d95550bd40f701"}, + {file = "coverage-6.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a022394996419142b33a0cf7274cb444c01d2bb123727c4bb0b9acabcb515dea"}, + {file = "coverage-6.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5a78cf2c43b13aa6b56003707c5203f28585944c277c1f3f109c7b041b16bd39"}, + {file = "coverage-6.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9229d074e097f21dfe0643d9d0140ee7433814b3f0fc3706b4abffd1e3038632"}, + {file = "coverage-6.4-cp310-cp310-win32.whl", hash = "sha256:fb45fe08e1abc64eb836d187b20a59172053999823f7f6ef4f18a819c44ba16f"}, + {file = "coverage-6.4-cp310-cp310-win_amd64.whl", hash = "sha256:3cfd07c5889ddb96a401449109a8b97a165be9d67077df6802f59708bfb07720"}, + {file = "coverage-6.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:03014a74023abaf5a591eeeaf1ac66a73d54eba178ff4cb1fa0c0a44aae70383"}, + {file = "coverage-6.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c82f2cd69c71698152e943f4a5a6b83a3ab1db73b88f6e769fabc86074c3b08"}, + {file = "coverage-6.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b546cf2b1974ddc2cb222a109b37c6ed1778b9be7e6b0c0bc0cf0438d9e45a6"}, + {file = "coverage-6.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc173f1ce9ffb16b299f51c9ce53f66a62f4d975abe5640e976904066f3c835d"}, + {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c53ad261dfc8695062fc8811ac7c162bd6096a05a19f26097f411bdf5747aee7"}, + {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:eef5292b60b6de753d6e7f2d128d5841c7915fb1e3321c3a1fe6acfe76c38052"}, + {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:543e172ce4c0de533fa892034cce260467b213c0ea8e39da2f65f9a477425211"}, + {file = "coverage-6.4-cp37-cp37m-win32.whl", hash = "sha256:00c8544510f3c98476bbd58201ac2b150ffbcce46a8c3e4fb89ebf01998f806a"}, + {file = "coverage-6.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b84ab65444dcc68d761e95d4d70f3cfd347ceca5a029f2ffec37d4f124f61311"}, + {file = "coverage-6.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d548edacbf16a8276af13063a2b0669d58bbcfca7c55a255f84aac2870786a61"}, + {file = "coverage-6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:033ebec282793bd9eb988d0271c211e58442c31077976c19c442e24d827d356f"}, + {file = "coverage-6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742fb8b43835078dd7496c3c25a1ec8d15351df49fb0037bffb4754291ef30ce"}, + {file = "coverage-6.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55fae115ef9f67934e9f1103c9ba826b4c690e4c5bcf94482b8b2398311bf9c"}, + {file = "coverage-6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd698341626f3c77784858427bad0cdd54a713115b423d22ac83a28303d1d95"}, + {file = "coverage-6.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:62d382f7d77eeeaff14b30516b17bcbe80f645f5cf02bb755baac376591c653c"}, + {file = "coverage-6.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:016d7f5cf1c8c84f533a3c1f8f36126fbe00b2ec0ccca47cc5731c3723d327c6"}, + {file = "coverage-6.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:69432946f154c6add0e9ede03cc43b96e2ef2733110a77444823c053b1ff5166"}, + {file = "coverage-6.4-cp38-cp38-win32.whl", hash = "sha256:83bd142cdec5e4a5c4ca1d4ff6fa807d28460f9db919f9f6a31babaaa8b88426"}, + {file = "coverage-6.4-cp38-cp38-win_amd64.whl", hash = "sha256:4002f9e8c1f286e986fe96ec58742b93484195defc01d5cc7809b8f7acb5ece3"}, + {file = "coverage-6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e4f52c272fdc82e7c65ff3f17a7179bc5f710ebc8ce8a5cadac81215e8326740"}, + {file = "coverage-6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b5578efe4038be02d76c344007b13119b2b20acd009a88dde8adec2de4f630b5"}, + {file = "coverage-6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8099ea680201c2221f8468c372198ceba9338a5fec0e940111962b03b3f716a"}, + {file = "coverage-6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a00441f5ea4504f5abbc047589d09e0dc33eb447dc45a1a527c8b74bfdd32c65"}, + {file = "coverage-6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e76bd16f0e31bc2b07e0fb1379551fcd40daf8cdf7e24f31a29e442878a827c"}, + {file = "coverage-6.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8d2e80dd3438e93b19e1223a9850fa65425e77f2607a364b6fd134fcd52dc9df"}, + {file = "coverage-6.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:341e9c2008c481c5c72d0e0dbf64980a4b2238631a7f9780b0fe2e95755fb018"}, + {file = "coverage-6.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:21e6686a95025927775ac501e74f5940cdf6fe052292f3a3f7349b0abae6d00f"}, + {file = "coverage-6.4-cp39-cp39-win32.whl", hash = "sha256:968ed5407f9460bd5a591cefd1388cc00a8f5099de9e76234655ae48cfdbe2c3"}, + {file = "coverage-6.4-cp39-cp39-win_amd64.whl", hash = "sha256:e35217031e4b534b09f9b9a5841b9344a30a6357627761d4218818b865d45055"}, + {file = "coverage-6.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:e637ae0b7b481905358624ef2e81d7fb0b1af55f5ff99f9ba05442a444b11e45"}, + {file = "coverage-6.4.tar.gz", hash = "sha256:727dafd7f67a6e1cad808dc884bd9c5a2f6ef1f8f6d2f22b37b96cb0080d4f49"}, +] +distlib = [ + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, +] +filelock = [ + {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"}, + {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"}, +] +identify = [ + {file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"}, + {file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"}, + {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"}, +] +more-itertools = [ + {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, + {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, +] +nodeenv = [ + {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, + {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, +] +nox = [ + {file = "nox-2022.1.7-py3-none-any.whl", hash = "sha256:efee12f02d39405b16d68f60e7a06fe1fc450ae58669d6cdda8c7f48e3bae9e3"}, + {file = "nox-2022.1.7.tar.gz", hash = "sha256:b375238cebb0b9df2fab74b8d0ce1a50cd80df60ca2e13f38f539454fcd97d7e"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] +pre-commit = [ + {file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"}, + {file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pybind11 = [ + {file = "pybind11-2.9.2-py2.py3-none-any.whl", hash = "sha256:20f56674da31c96bca7569b91e60f2bd30d693f0728541412ec927574f7bc9df"}, + {file = "pybind11-2.9.2.tar.gz", hash = "sha256:e5541f8bccf9111d1a94f7897593b55c4cf1a28d5e8cfc8225a855651f011071"}, +] +pyodbc = [ + {file = "pyodbc-4.0.32-cp27-cp27m-win32.whl", hash = "sha256:2152ce6d5131d769ff5839aa762e12d844c95e9ec4bb2f666e8cd9dfa1ae2240"}, + {file = "pyodbc-4.0.32-cp27-cp27m-win_amd64.whl", hash = "sha256:56ec4974096d40d6c62a228799122dbc2ade6c4045cc5d31860212a32cae95b1"}, + {file = "pyodbc-4.0.32-cp36-cp36m-win32.whl", hash = "sha256:699c080b1c1f7b4afc368b3521fd1161f46a10223443692a249cb01d90949b31"}, + {file = "pyodbc-4.0.32-cp36-cp36m-win_amd64.whl", hash = "sha256:0d4e14adb149cae45da37fa87aa297055156dae6e89ca3c75493d3d62d78e543"}, + {file = "pyodbc-4.0.32-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6c1e1c1fe747b0f6419e8df0b5c43161e7437dbf72f93f9fcfb9b7358fad3e12"}, + {file = "pyodbc-4.0.32-cp37-cp37m-win32.whl", hash = "sha256:bbc07517f339e019ee9f1fe679c4241251d11ca2124567616f67d62e73c29fc0"}, + {file = "pyodbc-4.0.32-cp37-cp37m-win_amd64.whl", hash = "sha256:e81ebf9cab80a6eaba7922dea02036e9f8a507a7b818856b8008a02d6fc0d2ab"}, + {file = "pyodbc-4.0.32-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0e4178e9b93329bbba17555882008e36a114179d06033b813a13b254dcd755d0"}, + {file = "pyodbc-4.0.32-cp38-cp38-win32.whl", hash = "sha256:c066f032e69fd71e9fadb3a380dfe8ecd1728b40a2bf38f76054d284f8523b29"}, + {file = "pyodbc-4.0.32-cp38-cp38-win_amd64.whl", hash = "sha256:736acad1b264ddb7313058dfe37265b0c5160c1c2a9d1ffd391347c025eb5dd1"}, + {file = "pyodbc-4.0.32-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:339d8aa633b0c65be5149c3378c7e3b5bead94dc8bb023a715b416bd047a008e"}, + {file = "pyodbc-4.0.32-cp39-cp39-win_amd64.whl", hash = "sha256:cda790bdc25bfad12d4fb9ba93368275802f7f9ecfa4c9c65e982d3a7fc35f2e"}, + {file = "pyodbc-4.0.32.tar.gz", hash = "sha256:9be5f0c3590655e1968488410fe3528bb8023d527e7ccec1f663d64245071a6b"}, +] +pyparsing = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] +pytest = [ + {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, + {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, +] +pytest-cov = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] +pytest-json-report = [ + {file = "pytest-json-report-1.5.0.tar.gz", hash = "sha256:2dde3c647851a19b5f3700729e8310a6e66efb2077d674f27ddea3d34dc615de"}, + {file = "pytest_json_report-1.5.0-py3-none-any.whl", hash = "sha256:9897b68c910b12a2e48dd849f9a284b2c79a732a8a9cb398452ddd23d3c8c325"}, +] +pytest-metadata = [ + {file = "pytest-metadata-1.11.0.tar.gz", hash = "sha256:71b506d49d34e539cc3cfdb7ce2c5f072bea5c953320002c95968e0238f8ecf1"}, + {file = "pytest_metadata-1.11.0-py2.py3-none-any.whl", hash = "sha256:576055b8336dd4a9006dd2a47615f76f2f8c30ab12b1b1c039d99e834583523f"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +sqlalchemy = [ + {file = "SQLAlchemy-1.3.24-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:87a2725ad7d41cd7376373c15fd8bf674e9c33ca56d0b8036add2d634dba372e"}, + {file = "SQLAlchemy-1.3.24-cp27-cp27m-win32.whl", hash = "sha256:f597a243b8550a3a0b15122b14e49d8a7e622ba1c9d29776af741f1845478d79"}, + {file = "SQLAlchemy-1.3.24-cp27-cp27m-win_amd64.whl", hash = "sha256:fc4cddb0b474b12ed7bdce6be1b9edc65352e8ce66bc10ff8cbbfb3d4047dbf4"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:f1149d6e5c49d069163e58a3196865e4321bad1803d7886e07d8710de392c548"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:14f0eb5db872c231b20c18b1e5806352723a3a89fb4254af3b3e14f22eaaec75"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:e98d09f487267f1e8d1179bf3b9d7709b30a916491997137dd24d6ae44d18d79"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:fc1f2a5a5963e2e73bac4926bdaf7790c4d7d77e8fc0590817880e22dd9d0b8b"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-win32.whl", hash = "sha256:f3c5c52f7cb8b84bfaaf22d82cb9e6e9a8297f7c2ed14d806a0f5e4d22e83fb7"}, + {file = "SQLAlchemy-1.3.24-cp35-cp35m-win_amd64.whl", hash = "sha256:0352db1befcbed2f9282e72843f1963860bf0e0472a4fa5cf8ee084318e0e6ab"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:2ed6343b625b16bcb63c5b10523fd15ed8934e1ed0f772c534985e9f5e73d894"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:34fcec18f6e4b24b4a5f6185205a04f1eab1e56f8f1d028a2a03694ebcc2ddd4"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e47e257ba5934550d7235665eee6c911dc7178419b614ba9e1fbb1ce6325b14f"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:816de75418ea0953b5eb7b8a74933ee5a46719491cd2b16f718afc4b291a9658"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-win32.whl", hash = "sha256:26155ea7a243cbf23287f390dba13d7927ffa1586d3208e0e8d615d0c506f996"}, + {file = "SQLAlchemy-1.3.24-cp36-cp36m-win_amd64.whl", hash = "sha256:f03bd97650d2e42710fbe4cf8a59fae657f191df851fc9fc683ecef10746a375"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:a006d05d9aa052657ee3e4dc92544faae5fcbaafc6128217310945610d862d39"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1e2f89d2e5e3c7a88e25a3b0e43626dba8db2aa700253023b82e630d12b37109"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0d5d862b1cfbec5028ce1ecac06a3b42bc7703eb80e4b53fceb2738724311443"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:0172423a27fbcae3751ef016663b72e1a516777de324a76e30efa170dbd3dd2d"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-win32.whl", hash = "sha256:d37843fb8df90376e9e91336724d78a32b988d3d20ab6656da4eb8ee3a45b63c"}, + {file = "SQLAlchemy-1.3.24-cp37-cp37m-win_amd64.whl", hash = "sha256:c10ff6112d119f82b1618b6dc28126798481b9355d8748b64b9b55051eb4f01b"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:861e459b0e97673af6cc5e7f597035c2e3acdfb2608132665406cded25ba64c7"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5de2464c254380d8a6c20a2746614d5a436260be1507491442cf1088e59430d2"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d375d8ccd3cebae8d90270f7aa8532fe05908f79e78ae489068f3b4eee5994e8"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:014ea143572fee1c18322b7908140ad23b3994036ef4c0d630110faf942652f8"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-win32.whl", hash = "sha256:6607ae6cd3a07f8a4c3198ffbf256c261661965742e2b5265a77cd5c679c9bba"}, + {file = "SQLAlchemy-1.3.24-cp38-cp38-win_amd64.whl", hash = "sha256:fcb251305fa24a490b6a9ee2180e5f8252915fb778d3dafc70f9cc3f863827b9"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:01aa5f803db724447c1d423ed583e42bf5264c597fd55e4add4301f163b0be48"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4d0e3515ef98aa4f0dc289ff2eebb0ece6260bbf37c2ea2022aad63797eacf60"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:bce28277f308db43a6b4965734366f533b3ff009571ec7ffa583cb77539b84d6"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:8110e6c414d3efc574543109ee618fe2c1f96fa31833a1ff36cc34e968c4f233"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-win32.whl", hash = "sha256:ee5f5188edb20a29c1cc4a039b074fdc5575337c9a68f3063449ab47757bb064"}, + {file = "SQLAlchemy-1.3.24-cp39-cp39-win_amd64.whl", hash = "sha256:09083c2487ca3c0865dc588e07aeaa25416da3d95f7482c07e92f47e080aa17b"}, + {file = "SQLAlchemy-1.3.24.tar.gz", hash = "sha256:ebbb777cbf9312359b897bf81ba00dae0f5cb69fba2a18265dcc18a6f5ef7519"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +turbodbc = [ + {file = "turbodbc-3.3.0.tar.gz", hash = "sha256:4e1fce94926f756bfec9d2dcc54d4187fad60ac352617ed805c6356ee7ae0ece"}, +] +typing-extensions = [ + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, +] +urlscan = [ + {file = "urlscan-0.9.9-py3-none-any.whl", hash = "sha256:864f5332520f4fafe67d68e023aefc5636993cedb69145e4d9bb3a2884ee34ed"}, + {file = "urlscan-0.9.9.tar.gz", hash = "sha256:da66b99b3364f97d11ecfc105b8c95dd155bd08d8313dd9cc6472791493480d1"}, +] +urwid = [ + {file = "urwid-2.1.2.tar.gz", hash = "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"}, +] +virtualenv = [ + {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, + {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, +] +wcwidth = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] +zipp = [ + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, +] From 90c9ab46fb93d5074c47085b33794451573e8c9a Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 12:21:12 +0200 Subject: [PATCH 15/62] Delete deprecated requirements*.txt files --- requirements.txt | 2 -- requirements_dev.txt | 5 ----- requirements_extras.txt | 1 - requirements_test.txt | 4 ---- 4 files changed, 12 deletions(-) delete mode 100644 requirements.txt delete mode 100644 requirements_dev.txt delete mode 100644 requirements_extras.txt delete mode 100644 requirements_test.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index fd806b74..00000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -SQLAlchemy==1.3.24 # rq.filter: >=1.3.0,<1.4 -pyodbc==4.0.32 # rq.filter: >=4,<5 diff --git a/requirements_dev.txt b/requirements_dev.txt deleted file mode 100644 index 80d8bb89..00000000 --- a/requirements_dev.txt +++ /dev/null @@ -1,5 +0,0 @@ --r requirements_test.txt -nox>=2022.1.7 -urlscan>=0.9.9 -pytest-json-report>=1.5.0 - diff --git a/requirements_extras.txt b/requirements_extras.txt deleted file mode 100644 index 078e187a..00000000 --- a/requirements_extras.txt +++ /dev/null @@ -1 +0,0 @@ -turbodbc==3.3.0 # 4.0.0 introduced some breaking change (e.g. drops Python 2.7 support) diff --git a/requirements_test.txt b/requirements_test.txt deleted file mode 100644 index bfb232af..00000000 --- a/requirements_test.txt +++ /dev/null @@ -1,4 +0,0 @@ --r requirements.txt -pytest>=3.1.0,<5.4 #TODO: test run fails with 5.4 -pytest-cov>=2.7.0 #avoid https://github.com/z4r/python-coveralls/issues/66 -mock>=2.0.0 From d7cba054146c235d1e3148eec69ee763494ab709 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 12:21:38 +0200 Subject: [PATCH 16/62] Remove deprecated setup.py --- setup.py | 54 ------------------------------------------------------ 1 file changed, 54 deletions(-) delete mode 100644 setup.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 576a2cd9..00000000 --- a/setup.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -Defines the setup for this package. - -Do not forget to document your changes in CHANGES.md - -:file: setup.py -:authors: Blue Yonder GmbH, Exasol AG -:date: 2014/02/11 -""" -import os - -from setuptools import setup - -# Get long_description from README.md: -here = os.path.dirname(os.path.abspath(__file__)) -long_description = "" -with open(os.path.join(here, "README.rst")) as f: - long_description = f.read().strip() - -setup( - name="sqlalchemy_exasol", - setup_requires=["setuptools_scm"], - license="License :: OSI Approved :: BSD License", - url="https://github.com/exasol/sqlalchemy-exasol", - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Topic :: Database", - ], - description="EXASOL dialect for SQLAlchemy", - long_description=long_description, - author="Blue Yonder GmbH, Exasol AG", - author_email="opensource@exasol.com", - packages=["sqlalchemy_exasol"], - install_requires=["SQLAlchemy>=1.3.24, <1.4", "pyodbc>=4.0.32", "six>=1.5"], - extras_require={"turbodbc": ["turbodbc>=3.3.0, <4"]}, - tests_require=["pytest", "mock>=1.0.1"], - test_suite="pytest.main", - use_scm_version={"write_to": "sqlalchemy_exasol/_version.py"}, - entry_points={ - "sqlalchemy.dialects": [ - "exa.pyodbc = sqlalchemy_exasol.pyodbc:EXADialect_pyodbc", - "exa.turbodbc = sqlalchemy_exasol.turbodbc:EXADialect_turbodbc", - ] - }, -) From 55d17cb1ca6a665371e8a74f87b974da81d07e8b Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 12:24:51 +0200 Subject: [PATCH 17/62] Update comment in generated file according to code review --- scripts/version_check.py | 2 +- sqlalchemy_exasol/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/version_check.py b/scripts/version_check.py index a51b3f59..cf395737 100644 --- a/scripts/version_check.py +++ b/scripts/version_check.py @@ -14,7 +14,7 @@ # fmt: off _VERSION_MODULE_TEMPLATE = cleandoc(''' # ATTENTION: -# This file is generated, do not edit this file manually! +# This file is generated, do not edit it manually! # If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. MAJOR = {major} diff --git a/sqlalchemy_exasol/version.py b/sqlalchemy_exasol/version.py index 38ddb72b..2c9af742 100644 --- a/sqlalchemy_exasol/version.py +++ b/sqlalchemy_exasol/version.py @@ -1,5 +1,5 @@ # ATTENTION: -# This file is generated, do not edit this file manually! +# This file is generated, do not edit it manually! # If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. MAJOR = 2 From 1485b865b6e6313da2daf92e7f3d67b28fbe1cc5 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 12:51:47 +0200 Subject: [PATCH 18/62] Update CI workflow to use poetry --- .github/workflows/CI.yml | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7a6d9a85..baed2ca8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -40,23 +40,21 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install via apt - run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev - - - name: Install pipenv - uses: dschep/install-pipenv-action@v1 - - - name: Pip install requirements - uses: BSFishy/pip-action@v1 + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 with: - requirements: requirements_dev.txt + poetry-version: 1.1.13 - - name: Pip install extra requirements - uses: BSFishy/pip-action@v1 - with: - requirements: requirements_extras.txt + - name: Install python project dependencies + run: poetry install + + - name: Install python project dependencies including trubodbc + run: poetry install --extras "turbodbc" if: ${{ matrix.connector == 'turbodbc' }} + - name: Install via apt + run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev + - name: Checkout test environment run: git clone --depth 1 --branch ${ITDE_TAG} ${ITDE_URL} working-directory: .. @@ -76,10 +74,8 @@ jobs: strategy: matrix: python: [3.7] - connector: - - pyodbc - name: Build Package (Python-${{ matrix.python }}, Connector-${{ matrix.connector }}) + name: Build Package Python-${{ matrix.python }} steps: @@ -94,11 +90,13 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install pipenv - uses: dschep/install-pipenv-action@v1 + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 - - name: Install Wheel - run: pip install wheel + - name: Install python project dependencies + run: poetry install --extras "turbodbc" - name: Build sdist and wheel packages - run: python setup.py sdist bdist_wheel + run: poetry build From 2ab87f8cf88b96b2307667ff289c56aab384a4f9 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 12:55:29 +0200 Subject: [PATCH 19/62] Fix command invocation to use poetry --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index baed2ca8..763e67ad 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -63,10 +63,10 @@ jobs: ITDE_TAG: "0.10.0" - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} - run: nox -s "check-links" + run: poetry run nox -s "check-links" - name: Run Test for Python ${{ matrix.python }} using ${{ matrix.connector }} - run: nox -s "verify(connector='${{ matrix.connector }}')" + run: poetry run nox -s "verify(connector='${{ matrix.connector }}')" build_package: runs-on: ubuntu-latest From 362c006f156159298a1738119b0ff63bfe779290 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 13:11:40 +0200 Subject: [PATCH 20/62] Fix import of version module --- sqlalchemy_exasol/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sqlalchemy_exasol/__init__.py b/sqlalchemy_exasol/__init__.py index 6dcb961f..3ab33b26 100644 --- a/sqlalchemy_exasol/__init__.py +++ b/sqlalchemy_exasol/__init__.py @@ -1,5 +1,6 @@ -from version import VERSION +from sqlalchemy_exasol.version import VERSION from sqlalchemy_exasol import base, pyodbc + __version__ = VERSION # default dialect From 42a4914f0b4998bb8243f8b629eeb0fe6af3a983 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 13:19:17 +0200 Subject: [PATCH 21/62] Fix installation order --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 763e67ad..de5ee218 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -35,6 +35,9 @@ jobs: - name: Setup integration-test-docker-environment uses: actions/setup-python@v2 + - name: Install via apt + run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev + - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v2 with: @@ -52,9 +55,6 @@ jobs: run: poetry install --extras "turbodbc" if: ${{ matrix.connector == 'turbodbc' }} - - name: Install via apt - run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev - - name: Checkout test environment run: git clone --depth 1 --branch ${ITDE_TAG} ${ITDE_URL} working-directory: .. @@ -96,7 +96,7 @@ jobs: poetry-version: 1.1.13 - name: Install python project dependencies - run: poetry install --extras "turbodbc" + run: poetry install - name: Build sdist and wheel packages run: poetry build From 2309b94a0d694b2671b7f878dac687335b07e0b6 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 13:40:33 +0200 Subject: [PATCH 22/62] Use python built in mock library --- test/test_exadialect_pyodbc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_exadialect_pyodbc.py b/test/test_exadialect_pyodbc.py index 3da6fd9d..469ee191 100644 --- a/test/test_exadialect_pyodbc.py +++ b/test/test_exadialect_pyodbc.py @@ -1,6 +1,6 @@ import pyodbc import pytest -from mock import Mock +from unittest.mock import Mock from sqlalchemy import testing from sqlalchemy.engine import url as sa_url from sqlalchemy.pool import _ConnectionFairy From 43c7093d1ee1a230186b1a3a4005015afd62d8d4 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 13:52:44 +0200 Subject: [PATCH 23/62] Remove deprecated version parsing --- sqlalchemy_exasol/pyodbc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sqlalchemy_exasol/pyodbc.py b/sqlalchemy_exasol/pyodbc.py index e5af6470..7507a1f4 100644 --- a/sqlalchemy_exasol/pyodbc.py +++ b/sqlalchemy_exasol/pyodbc.py @@ -9,7 +9,7 @@ import re import sys import logging -from distutils.version import LooseVersion +from packaging import version from sqlalchemy import sql from sqlalchemy.engine import reflection @@ -33,7 +33,7 @@ def __init__(self, **kw): def get_driver_version(self, connection): # LooseVersion will also work with interim versions like '4.2.7dev1' or '5.0.rc4' if self.driver_version is None: - self.driver_version = LooseVersion( + self.driver_version = version.parse( connection.connection.getinfo(self.dbapi.SQL_DRIVER_VER) or "2.0.0" ) return self.driver_version @@ -41,7 +41,7 @@ def get_driver_version(self, connection): def _get_server_version_info(self, connection): if self.server_version_info is None: # need to check if current version of EXAODBC returns proper server version - if self.get_driver_version(connection) >= LooseVersion("4.2.1"): + if self.get_driver_version(connection) >= version.parse("4.2.1"): # v4.2.1 and above should deliver usable SQL_DBMS_VER result = connection.connection.getinfo(self.dbapi.SQL_DBMS_VER).split( "." From 2329c24853a3d472c1225dce0eb75a7ed966bdc9 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 13:56:05 +0200 Subject: [PATCH 24/62] Add missing newline --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f097022a..0ba73edd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,4 +8,4 @@ repos: always_run: true verbose: true language: system - entry: python scripts/version_check.py sqlalchemy_exasol/version.py \ No newline at end of file + entry: python scripts/version_check.py sqlalchemy_exasol/version.py From 76737022bc6178bc9f2919d82a3ad049ca15efad Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 1 Jun 2022 14:49:03 +0200 Subject: [PATCH 25/62] Rename workflow step --- .github/workflows/CI.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index de5ee218..00687268 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -75,7 +75,7 @@ jobs: matrix: python: [3.7] - name: Build Package Python-${{ matrix.python }} + name: Build Package steps: @@ -95,8 +95,5 @@ jobs: with: poetry-version: 1.1.13 - - name: Install python project dependencies - run: poetry install - - name: Build sdist and wheel packages run: poetry build From d86bf11c7b377612f7a245455fe09629dbec5664 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:30:33 +0200 Subject: [PATCH 26/62] Update .github/workflows/CI.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: chπ --- .github/workflows/CI.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 00687268..ed925a94 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,9 +32,6 @@ jobs: - name: Fetch sqlalchemy_exasol code from repository uses: actions/checkout@v2 - - name: Setup integration-test-docker-environment - uses: actions/setup-python@v2 - - name: Install via apt run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev From 4d00df4c4399e5edabf90a1bc05e3ffe995c2e35 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:31:01 +0200 Subject: [PATCH 27/62] Update .github/workflows/CI.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: chπ --- .github/workflows/CI.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ed925a94..6870be31 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -36,9 +36,10 @@ jobs: run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} + cache: 'poetry' - name: Install poetry uses: abatilo/actions-poetry@v2.0.0 From ef898741c2481717c74c01588c14b0907beed579 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:41:06 +0200 Subject: [PATCH 28/62] Add check-links workflow --- .github/workflows/check-links.yaml | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/check-links.yaml diff --git a/.github/workflows/check-links.yaml b/.github/workflows/check-links.yaml new file mode 100644 index 00000000..e136b7d6 --- /dev/null +++ b/.github/workflows/check-links.yaml @@ -0,0 +1,41 @@ +name: Check Links + +on: + push: + branches-ignore: + - 'master' + pull_request: + branches-ignore: + - 'master' + +jobs: + run_tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python: [3.7] + + name: Check Links (Python-${{ matrix.python }}) + + steps: + + - name: Fetch sqlalchemy_exasol code from repository + uses: actions/checkout@v2 + + - name: Setup Python ${{ matrix.python }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python }} + cache: 'poetry' + + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + + - name: Install python project dependencies + run: poetry install --dev-only + + - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} + run: poetry run nox -s "check-links" From 8aea7acab54a46ac0458e0f2fc89c57183b9c29e Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:41:54 +0200 Subject: [PATCH 29/62] Add packaging dependency explicitly --- poetry.lock | 6 +++--- pyproject.toml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index b1c836af..c18bd1f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -166,7 +166,7 @@ tox_to_nox = ["jinja2", "tox"] name = "packaging" version = "21.3" description = "Core utilities for Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" @@ -247,7 +247,7 @@ python-versions = "*" name = "pyparsing" version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" +category = "main" optional = false python-versions = ">=3.6.8" @@ -455,7 +455,7 @@ turbodbc = ["turbodbc"] [metadata] lock-version = "1.1" python-versions = ">=3.7,<4.0" -content-hash = "fde39bfa9f47038eec3cedef28d4fcad8c722e31865f1a4ecae9026d1b843b52" +content-hash = "009bb8a94d9a18e6a37f79dc3080d6fefe88ef348e100bd5021eefbe34949c05" [metadata.files] argcomplete = [ diff --git a/pyproject.toml b/pyproject.toml index 17d88b65..67a79129 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ python = ">=3.7,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" turbodbc = { version = ">=3.3.0,<4", optional = true } +packaging = "^21.3" [tool.poetry.dev-dependencies] nox = ">=2022.1.7" From d8c6dac6f3a021f815fff2625c7f8af17ada493c Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:48:10 +0200 Subject: [PATCH 30/62] Update ci workflow to support caching --- .github/workflows/{CI.yml => ci.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{CI.yml => ci.yaml} (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/ci.yaml similarity index 100% rename from .github/workflows/CI.yml rename to .github/workflows/ci.yaml From 9cd20510e8253900ef7ea1f1c578b155714bbff6 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:52:45 +0200 Subject: [PATCH 31/62] Fix github workflows to install poetry previous to the python setup If poetry is not installed before the python action gets installed/run it will fail if caching is enabled. --- .github/workflows/check-links.yaml | 10 +++++----- .github/workflows/ci.yaml | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/check-links.yaml b/.github/workflows/check-links.yaml index e136b7d6..99c14cf2 100644 --- a/.github/workflows/check-links.yaml +++ b/.github/workflows/check-links.yaml @@ -23,17 +23,17 @@ jobs: - name: Fetch sqlalchemy_exasol code from repository uses: actions/checkout@v2 + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} cache: 'poetry' - - name: Install poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: 1.1.13 - - name: Install python project dependencies run: poetry install --dev-only diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6870be31..43d33329 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,17 +35,17 @@ jobs: - name: Install via apt run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} cache: 'poetry' - - name: Install poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: 1.1.13 - - name: Install python project dependencies run: poetry install @@ -84,9 +84,10 @@ jobs: run: git fetch origin +refs/tags/*:refs/tags/* - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} + cache: 'poetry' - name: Install poetry uses: abatilo/actions-poetry@v2.0.0 From 50655868fc1f5ef42bcfa2a13a1113f383de120a Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:56:57 +0200 Subject: [PATCH 32/62] Fix check-links workflow --- .github/workflows/check-links.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-links.yaml b/.github/workflows/check-links.yaml index 99c14cf2..f558891b 100644 --- a/.github/workflows/check-links.yaml +++ b/.github/workflows/check-links.yaml @@ -35,7 +35,7 @@ jobs: cache: 'poetry' - name: Install python project dependencies - run: poetry install --dev-only + run: poetry install --no-root - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} run: poetry run nox -s "check-links" From bad8906c8761d84880d561357a9d0d1def8e2b04 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 2 Jun 2022 08:57:48 +0200 Subject: [PATCH 33/62] Renamed workflow check-links to link-check --- .github/workflows/{check-links.yaml => link-check.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{check-links.yaml => link-check.yaml} (100%) diff --git a/.github/workflows/check-links.yaml b/.github/workflows/link-check.yaml similarity index 100% rename from .github/workflows/check-links.yaml rename to .github/workflows/link-check.yaml From ce3aaddacaafb0ee0f7f55838c9c9dc9d73da2ae Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Fri, 3 Jun 2022 10:29:40 +0200 Subject: [PATCH 34/62] Fix issue of wrong selected python version in github action --- .github/workflows/ci.yaml | 12 +++++------- .github/workflows/link-check.yaml | 11 +++++------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 43d33329..5ce2aaa5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,16 +35,15 @@ jobs: - name: Install via apt run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev - - name: Install poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: 1.1.13 - - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} - cache: 'poetry' + + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 - name: Install python project dependencies run: poetry install @@ -87,7 +86,6 @@ jobs: uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} - cache: 'poetry' - name: Install poetry uses: abatilo/actions-poetry@v2.0.0 diff --git a/.github/workflows/link-check.yaml b/.github/workflows/link-check.yaml index f558891b..94a41708 100644 --- a/.github/workflows/link-check.yaml +++ b/.github/workflows/link-check.yaml @@ -23,16 +23,15 @@ jobs: - name: Fetch sqlalchemy_exasol code from repository uses: actions/checkout@v2 - - name: Install poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: 1.1.13 - - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python }} - cache: 'poetry' + + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 - name: Install python project dependencies run: poetry install --no-root From 64ac3863233604ce99dabacc2b6c1b2aba0ad05d Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:09:36 +0200 Subject: [PATCH 35/62] Rework CI-CD workflow to use poetry --- .github/workflows/{CI-CD.yml => ci-cd.yml} | 50 +++++++++------------- 1 file changed, 21 insertions(+), 29 deletions(-) rename .github/workflows/{CI-CD.yml => ci-cd.yml} (69%) diff --git a/.github/workflows/CI-CD.yml b/.github/workflows/ci-cd.yml similarity index 69% rename from .github/workflows/CI-CD.yml rename to .github/workflows/ci-cd.yml index 28a9594b..2f72f26c 100644 --- a/.github/workflows/CI-CD.yml +++ b/.github/workflows/ci-cd.yml @@ -31,26 +31,24 @@ jobs: - name: Setup integration-test-docker-environment uses: actions/setup-python@v2 + - name: Install via apt + run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev + - name: Setup Python ${{ matrix.python }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python }} - - name: Install via apt - run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev - - - name: Install pipenv - uses: dschep/install-pipenv-action@v1 - - - name: Pip install test requirements - uses: BSFishy/pip-action@v1 + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 with: - requirements: requirements_dev.txt + poetry-version: 1.1.13 - - name: Pip install extra requirements - uses: BSFishy/pip-action@v1 - with: - requirements: requirements_extras.txt + - name: Install python project dependencies + run: poetry install + + - name: Install python project dependencies including trubodbc + run: poetry install --extras "turbodbc" if: ${{ matrix.connector == 'turbodbc' }} - name: Checkout test environment @@ -61,10 +59,10 @@ jobs: ITDE_TAG: "0.10.0" - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} - run: nox -s "check-links" + run: poetry run nox -s "check-links" - name: Run Test for Python ${{ matrix.python }} using ${{ matrix.connector }} - run: nox -s "verify(connector='${{ matrix.connector }}')" + run: poetry run nox -s "verify(connector='${{ matrix.connector }}')" upload_to_pypi: runs-on: ubuntu-latest @@ -73,10 +71,8 @@ jobs: strategy: matrix: python: [3.7] - connector: - - pyodbc - name: Upload to PyPI (Python-${{ matrix.python }}, Connector-${{ matrix.connector }}) + name: Build & Upload Package [PYPI] steps: @@ -91,17 +87,13 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install pipenv - uses: dschep/install-pipenv-action@v1 - - - name: Install Wheel - run: pip install wheel + - name: Install poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 - name: Build sdist and wheel packages - run: python setup.py sdist bdist_wheel + run: poetry build - - name: Push package to Pypi - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.pypi_token }} + - name: Push package to PYPI + run: poetry publish --username=__token__ --password=${{ secrets.pypi_token }} From d50aa3292e5bd8c41f6f8d0c622d452e7de8d4fd Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:19:20 +0200 Subject: [PATCH 36/62] Remove version file from ignore list --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 460c6be0..31c17298 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ develop-eggs .installed.cfg lib lib64 -sqlalchemy_exasol/_version.py # Installer logs pip-log.txt From aec032fa3b78439d08383b76ac44dc8c7b102320 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:21:07 +0200 Subject: [PATCH 37/62] Remove MANIFEST.in file --- MANIFEST.in | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index b0c2ac4c..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include versioneer.py -include sqlalchemy_exasol/_version.py -include README.rst From d0dc2852121fd19b5ed1cd473c569a0180205a26 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:33:58 +0200 Subject: [PATCH 38/62] Add dependabot updater to repository --- .github/dependabot.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..f7059a28 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 + + # Maintain dependencies for poetry + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 5 \ No newline at end of file From 7abe052e3584dfdd43c309f687708312786d9d5d Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:49:16 +0200 Subject: [PATCH 39/62] Update base python version to 3.8 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 67a79129..3f75f005 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ exclude = [] [tool.poetry.dependencies] -python = ">=3.7,<4.0" +python = ">=3.8,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" turbodbc = { version = ">=3.3.0,<4", optional = true } From c663056805d15640448e87e15e0590220262017b Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:49:57 +0200 Subject: [PATCH 40/62] Add pyupgrade commit hook to workspace --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ba73edd..1f555f70 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,3 +9,10 @@ repos: verbose: true language: system entry: python scripts/version_check.py sqlalchemy_exasol/version.py + +- repo: https://github.com/asottile/pyupgrade + rev: v2.34.0 + hooks: + - id: pyupgrade + args: ['--py38-plus'] + types: [python] From 40ddcbaa819d4f90bd1d8ca7679e9bec3d008b1b Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 08:56:13 +0200 Subject: [PATCH 41/62] Update python version(s) in github actions --- .github/workflows/ci-cd.yml | 7 +++++-- .github/workflows/ci.yaml | 7 +++++-- .github/workflows/link-check.yaml | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2f72f26c..df09c58d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -13,7 +13,10 @@ jobs: strategy: fail-fast: false matrix: - python: [3.7, 3.8, 3.9] + python: + - "3.8" + - "3.9" + - "3.10" connector: - pyodbc - turbodbc @@ -70,7 +73,7 @@ jobs: if: startsWith(github.event.ref, 'refs/tags') strategy: matrix: - python: [3.7] + python: [3.8] name: Build & Upload Package [PYPI] diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5ce2aaa5..d940ab50 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,10 @@ jobs: strategy: fail-fast: false matrix: - python: [3.7, 3.8, 3.9] + python: + - "3.8" + - "3.9" + - "3.10" connector: - pyodbc - turbodbc @@ -70,7 +73,7 @@ jobs: needs: run_tests strategy: matrix: - python: [3.7] + python: [3.8] name: Build Package diff --git a/.github/workflows/link-check.yaml b/.github/workflows/link-check.yaml index 94a41708..8bd87db3 100644 --- a/.github/workflows/link-check.yaml +++ b/.github/workflows/link-check.yaml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python: [3.7] + python: [3.8] name: Check Links (Python-${{ matrix.python }}) From 7aa97613f31c65131efb8c863b36df8e13865740 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:16:50 +0200 Subject: [PATCH 42/62] Bump version to 3.0.0 --- poetry.lock | 205 +++++++++++------------------------ pyproject.toml | 5 +- sqlalchemy_exasol/version.py | 4 +- 3 files changed, 70 insertions(+), 144 deletions(-) diff --git a/poetry.lock b/poetry.lock index c18bd1f7..5d9802fb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,9 +6,6 @@ category = "dev" optional = false python-versions = "*" -[package.dependencies] -importlib-metadata = {version = ">=0.23,<5", markers = "python_version == \"3.7\""} - [package.extras] test = ["coverage", "flake8", "pexpect", "wheel"] @@ -44,7 +41,7 @@ python-versions = ">=3.6.1" [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "dev" optional = false @@ -66,14 +63,14 @@ development = ["black", "flake8", "mypy", "pytest", "types-colorama"] [[package]] name = "coverage" -version = "6.4" +version = "6.4.1" description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -tomli = {version = "*", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""} +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] toml = ["tomli"] @@ -109,23 +106,6 @@ python-versions = ">=3.7" [package.extras] license = ["ukkonen"] -[[package]] -name = "importlib-metadata" -version = "4.11.4" -description = "Read metadata from Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] -perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] - [[package]] name = "more-itertools" version = "8.13.0" @@ -136,11 +116,11 @@ python-versions = ">=3.5" [[package]] name = "nodeenv" -version = "1.6.0" +version = "1.7.0" description = "Node.js virtual environment builder" category = "dev" optional = false -python-versions = "*" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" [[package]] name = "nox" @@ -153,10 +133,8 @@ python-versions = ">=3.6" [package.dependencies] argcomplete = ">=1.9.4,<2.0" colorlog = ">=2.6.1,<7.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} packaging = ">=20.9" py = ">=1.4.0,<2.0.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} virtualenv = ">=14.0.0" [package.extras] @@ -193,9 +171,6 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] @@ -210,7 +185,6 @@ python-versions = ">=3.7" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" @@ -224,17 +198,6 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -[[package]] -name = "pybind11" -version = "2.9.2" -description = "Seamless operability between C++11 and Python" -category = "main" -optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.extras] -global = ["pybind11-global (==2.9.2)"] - [[package]] name = "pyodbc" version = "4.0.32" @@ -266,7 +229,6 @@ python-versions = ">=3.5" atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=17.4.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} more-itertools = ">=4.0.0" packaging = "*" pluggy = ">=0.12,<1.0" @@ -327,7 +289,7 @@ python-versions = ">=3.6" name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" @@ -369,27 +331,19 @@ python-versions = ">=3.7" [[package]] name = "turbodbc" -version = "3.3.0" +version = "4.5.3" description = "turbodbc is a Python DB API 2.0 compatible ODBC driver" category = "main" -optional = true -python-versions = "*" - -[package.dependencies] -pybind11 = ">=2.2.0" -six = "*" +optional = false +python-versions = ">=3.8" [package.extras] -arrow = ["pyarrow (>=0.12,<0.16)"] -numpy = ["numpy (>=1.14.0)"] +arrow = ["pyarrow (>=1.0,<7.1.0)"] +numpy = ["numpy (>=1.19.0)"] -[[package]] -name = "typing-extensions" -version = "4.2.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" -optional = false -python-versions = ">=3.7" +[package.source] +type = "file" +url = "../../Downloads/turbodbc-4.5.3.tar.gz" [[package]] name = "urlscan" @@ -412,7 +366,7 @@ python-versions = "*" [[package]] name = "virtualenv" -version = "20.14.1" +version = "20.15.1" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -421,7 +375,6 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] distlib = ">=0.3.1,<1" filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} platformdirs = ">=2,<3" six = ">=1.9.0,<2" @@ -437,25 +390,13 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "zipp" -version = "3.8.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] - [extras] turbodbc = ["turbodbc"] [metadata] lock-version = "1.1" -python-versions = ">=3.7,<4.0" -content-hash = "009bb8a94d9a18e6a37f79dc3080d6fefe88ef348e100bd5021eefbe34949c05" +python-versions = ">=3.8,<4.0" +content-hash = "bbe001e6f23ed11f269f8b7b9a0f79353016a662a7fec78095b27f14dab55192" [metadata.files] argcomplete = [ @@ -475,55 +416,55 @@ cfgv = [ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] colorlog = [ {file = "colorlog-6.6.0-py2.py3-none-any.whl", hash = "sha256:351c51e866c86c3217f08e4b067a7974a678be78f07f85fc2d55b8babde6d94e"}, {file = "colorlog-6.6.0.tar.gz", hash = "sha256:344f73204009e4c83c5b6beb00b3c45dc70fcdae3c80db919e0a4171d006fde8"}, ] coverage = [ - {file = "coverage-6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50ed480b798febce113709846b11f5d5ed1e529c88d8ae92f707806c50297abf"}, - {file = "coverage-6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26f8f92699756cb7af2b30720de0c5bb8d028e923a95b6d0c891088025a1ac8f"}, - {file = "coverage-6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60c2147921da7f4d2d04f570e1838db32b95c5509d248f3fe6417e91437eaf41"}, - {file = "coverage-6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:750e13834b597eeb8ae6e72aa58d1d831b96beec5ad1d04479ae3772373a8088"}, - {file = "coverage-6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af5b9ee0fc146e907aa0f5fb858c3b3da9199d78b7bb2c9973d95550bd40f701"}, - {file = "coverage-6.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a022394996419142b33a0cf7274cb444c01d2bb123727c4bb0b9acabcb515dea"}, - {file = "coverage-6.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5a78cf2c43b13aa6b56003707c5203f28585944c277c1f3f109c7b041b16bd39"}, - {file = "coverage-6.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9229d074e097f21dfe0643d9d0140ee7433814b3f0fc3706b4abffd1e3038632"}, - {file = "coverage-6.4-cp310-cp310-win32.whl", hash = "sha256:fb45fe08e1abc64eb836d187b20a59172053999823f7f6ef4f18a819c44ba16f"}, - {file = "coverage-6.4-cp310-cp310-win_amd64.whl", hash = "sha256:3cfd07c5889ddb96a401449109a8b97a165be9d67077df6802f59708bfb07720"}, - {file = "coverage-6.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:03014a74023abaf5a591eeeaf1ac66a73d54eba178ff4cb1fa0c0a44aae70383"}, - {file = "coverage-6.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c82f2cd69c71698152e943f4a5a6b83a3ab1db73b88f6e769fabc86074c3b08"}, - {file = "coverage-6.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b546cf2b1974ddc2cb222a109b37c6ed1778b9be7e6b0c0bc0cf0438d9e45a6"}, - {file = "coverage-6.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc173f1ce9ffb16b299f51c9ce53f66a62f4d975abe5640e976904066f3c835d"}, - {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c53ad261dfc8695062fc8811ac7c162bd6096a05a19f26097f411bdf5747aee7"}, - {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:eef5292b60b6de753d6e7f2d128d5841c7915fb1e3321c3a1fe6acfe76c38052"}, - {file = "coverage-6.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:543e172ce4c0de533fa892034cce260467b213c0ea8e39da2f65f9a477425211"}, - {file = "coverage-6.4-cp37-cp37m-win32.whl", hash = "sha256:00c8544510f3c98476bbd58201ac2b150ffbcce46a8c3e4fb89ebf01998f806a"}, - {file = "coverage-6.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b84ab65444dcc68d761e95d4d70f3cfd347ceca5a029f2ffec37d4f124f61311"}, - {file = "coverage-6.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d548edacbf16a8276af13063a2b0669d58bbcfca7c55a255f84aac2870786a61"}, - {file = "coverage-6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:033ebec282793bd9eb988d0271c211e58442c31077976c19c442e24d827d356f"}, - {file = "coverage-6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742fb8b43835078dd7496c3c25a1ec8d15351df49fb0037bffb4754291ef30ce"}, - {file = "coverage-6.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55fae115ef9f67934e9f1103c9ba826b4c690e4c5bcf94482b8b2398311bf9c"}, - {file = "coverage-6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd698341626f3c77784858427bad0cdd54a713115b423d22ac83a28303d1d95"}, - {file = "coverage-6.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:62d382f7d77eeeaff14b30516b17bcbe80f645f5cf02bb755baac376591c653c"}, - {file = "coverage-6.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:016d7f5cf1c8c84f533a3c1f8f36126fbe00b2ec0ccca47cc5731c3723d327c6"}, - {file = "coverage-6.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:69432946f154c6add0e9ede03cc43b96e2ef2733110a77444823c053b1ff5166"}, - {file = "coverage-6.4-cp38-cp38-win32.whl", hash = "sha256:83bd142cdec5e4a5c4ca1d4ff6fa807d28460f9db919f9f6a31babaaa8b88426"}, - {file = "coverage-6.4-cp38-cp38-win_amd64.whl", hash = "sha256:4002f9e8c1f286e986fe96ec58742b93484195defc01d5cc7809b8f7acb5ece3"}, - {file = "coverage-6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e4f52c272fdc82e7c65ff3f17a7179bc5f710ebc8ce8a5cadac81215e8326740"}, - {file = "coverage-6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b5578efe4038be02d76c344007b13119b2b20acd009a88dde8adec2de4f630b5"}, - {file = "coverage-6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8099ea680201c2221f8468c372198ceba9338a5fec0e940111962b03b3f716a"}, - {file = "coverage-6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a00441f5ea4504f5abbc047589d09e0dc33eb447dc45a1a527c8b74bfdd32c65"}, - {file = "coverage-6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e76bd16f0e31bc2b07e0fb1379551fcd40daf8cdf7e24f31a29e442878a827c"}, - {file = "coverage-6.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8d2e80dd3438e93b19e1223a9850fa65425e77f2607a364b6fd134fcd52dc9df"}, - {file = "coverage-6.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:341e9c2008c481c5c72d0e0dbf64980a4b2238631a7f9780b0fe2e95755fb018"}, - {file = "coverage-6.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:21e6686a95025927775ac501e74f5940cdf6fe052292f3a3f7349b0abae6d00f"}, - {file = "coverage-6.4-cp39-cp39-win32.whl", hash = "sha256:968ed5407f9460bd5a591cefd1388cc00a8f5099de9e76234655ae48cfdbe2c3"}, - {file = "coverage-6.4-cp39-cp39-win_amd64.whl", hash = "sha256:e35217031e4b534b09f9b9a5841b9344a30a6357627761d4218818b865d45055"}, - {file = "coverage-6.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:e637ae0b7b481905358624ef2e81d7fb0b1af55f5ff99f9ba05442a444b11e45"}, - {file = "coverage-6.4.tar.gz", hash = "sha256:727dafd7f67a6e1cad808dc884bd9c5a2f6ef1f8f6d2f22b37b96cb0080d4f49"}, + {file = "coverage-6.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b"}, + {file = "coverage-6.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068"}, + {file = "coverage-6.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4"}, + {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84"}, + {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad"}, + {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc"}, + {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749"}, + {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4"}, + {file = "coverage-6.4.1-cp310-cp310-win32.whl", hash = "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df"}, + {file = "coverage-6.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6"}, + {file = "coverage-6.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46"}, + {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982"}, + {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4"}, + {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb"}, + {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b"}, + {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3"}, + {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6"}, + {file = "coverage-6.4.1-cp37-cp37m-win32.whl", hash = "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e"}, + {file = "coverage-6.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28"}, + {file = "coverage-6.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54"}, + {file = "coverage-6.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9"}, + {file = "coverage-6.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13"}, + {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9"}, + {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605"}, + {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d"}, + {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428"}, + {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83"}, + {file = "coverage-6.4.1-cp38-cp38-win32.whl", hash = "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b"}, + {file = "coverage-6.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c"}, + {file = "coverage-6.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df"}, + {file = "coverage-6.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d"}, + {file = "coverage-6.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4"}, + {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3"}, + {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3"}, + {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8"}, + {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72"}, + {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264"}, + {file = "coverage-6.4.1-cp39-cp39-win32.whl", hash = "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9"}, + {file = "coverage-6.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397"}, + {file = "coverage-6.4.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815"}, + {file = "coverage-6.4.1.tar.gz", hash = "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c"}, ] distlib = [ {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, @@ -537,17 +478,13 @@ identify = [ {file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"}, {file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"}, ] -importlib-metadata = [ - {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"}, - {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"}, -] more-itertools = [ {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, ] nodeenv = [ - {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, - {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, ] nox = [ {file = "nox-2022.1.7-py3-none-any.whl", hash = "sha256:efee12f02d39405b16d68f60e7a06fe1fc450ae58669d6cdda8c7f48e3bae9e3"}, @@ -573,10 +510,6 @@ py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] -pybind11 = [ - {file = "pybind11-2.9.2-py2.py3-none-any.whl", hash = "sha256:20f56674da31c96bca7569b91e60f2bd30d693f0728541412ec927574f7bc9df"}, - {file = "pybind11-2.9.2.tar.gz", hash = "sha256:e5541f8bccf9111d1a94f7897593b55c4cf1a28d5e8cfc8225a855651f011071"}, -] pyodbc = [ {file = "pyodbc-4.0.32-cp27-cp27m-win32.whl", hash = "sha256:2152ce6d5131d769ff5839aa762e12d844c95e9ec4bb2f666e8cd9dfa1ae2240"}, {file = "pyodbc-4.0.32-cp27-cp27m-win_amd64.whl", hash = "sha256:56ec4974096d40d6c62a228799122dbc2ade6c4045cc5d31860212a32cae95b1"}, @@ -696,11 +629,7 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] turbodbc = [ - {file = "turbodbc-3.3.0.tar.gz", hash = "sha256:4e1fce94926f756bfec9d2dcc54d4187fad60ac352617ed805c6356ee7ae0ece"}, -] -typing-extensions = [ - {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, - {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, + {file = "turbodbc-4.5.3.tar.gz", hash = "sha256:72b78689bfa9f34c22bae6c7795b801da134c6fcb329101b3b690c0a79beb439"}, ] urlscan = [ {file = "urlscan-0.9.9-py3-none-any.whl", hash = "sha256:864f5332520f4fafe67d68e023aefc5636993cedb69145e4d9bb3a2884ee34ed"}, @@ -710,14 +639,10 @@ urwid = [ {file = "urwid-2.1.2.tar.gz", hash = "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"}, ] virtualenv = [ - {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, - {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, + {file = "virtualenv-20.15.1-py2.py3-none-any.whl", hash = "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf"}, + {file = "virtualenv-20.15.1.tar.gz", hash = "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] -zipp = [ - {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, - {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, -] diff --git a/pyproject.toml b/pyproject.toml index 3f75f005..405feb57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "sqlalchemy_exasol" -version = "2.4.0" +version = "3.0.0" description = "EXASOL dialect for SQLAlchemy" readme = "README.rst" license = "License :: OSI Approved :: BSD License" @@ -55,8 +55,8 @@ exclude = [] python = ">=3.8,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" -turbodbc = { version = ">=3.3.0,<4", optional = true } packaging = "^21.3" +turbodbc = {path = "../../Downloads/turbodbc-4.5.3.tar.gz"} [tool.poetry.dev-dependencies] nox = ">=2022.1.7" @@ -67,6 +67,7 @@ pytest-json-report = ">=1.5.0" pytest = ">=3.1.0,!=3.9.1,!=3.9.2,<6" pytest-cov = ">=2.7.0" pre-commit = "^2.19.0" +wheel = "^0.37.1" [tool.poetry.extras] turbodbc = ["turbodbc"] diff --git a/sqlalchemy_exasol/version.py b/sqlalchemy_exasol/version.py index 2c9af742..4ad95621 100644 --- a/sqlalchemy_exasol/version.py +++ b/sqlalchemy_exasol/version.py @@ -2,8 +2,8 @@ # This file is generated, do not edit it manually! # If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. -MAJOR = 2 -MINOR = 4 +MAJOR = 3 +MINOR = 0 PATCH = 0 VERSION = f"{MAJOR}.{MINOR}.{PATCH}" From fcec34da72a5cc8d546f6d001d0acd4b59c6731e Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:17:27 +0200 Subject: [PATCH 43/62] Removed verbose flag from pre commit hook --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f555f70..ff516453 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,6 @@ repos: - id: version-check name: Check if version(s) are in sync always_run: true - verbose: true language: system entry: python scripts/version_check.py sqlalchemy_exasol/version.py From dd3b839e06fd0e65e24c15368e4a5be4689244fc Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:28:40 +0200 Subject: [PATCH 44/62] Show CI instead of CI-CD status in README --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f69f3b4f..9f9e4c02 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ SQLAlchemy Dialect for EXASOL DB .. image:: https://github.com/exasol/sqlalchemy_exasol/workflows/CI-CD/badge.svg?branch=master - :target: https://github.com/exasol/sqlalchemy_exasol/actions?query=workflow%3ACI-CD + :target: https://github.com/exasol/sqlalchemy_exasol/actions?query=workflow%3ACI .. image:: https://img.shields.io/pypi/v/sqlalchemy_exasol :target: https://pypi.org/project/sqlalchemy-exasol/ :alt: PyPI Version From 66097048fe0930d8f5ea26a82c86e670e1f1b70c Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:30:12 +0200 Subject: [PATCH 45/62] Update information about minimum python version --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9f9e4c02..30955e41 100644 --- a/README.rst +++ b/README.rst @@ -37,7 +37,7 @@ On Linux/Unix like systems you need: Turbodbc support ```````````````` -- You can use Turbodbc with sqlalchemy_exasol if you use a python version >= 3.7. +- You can use Turbodbc with sqlalchemy_exasol if you use a python version >= 3.8. - Multi row update is not supported, see `test/test_update.py `_ for an example From 037f906f99cf89bf00209932d645d468d9d833af Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:46:10 +0200 Subject: [PATCH 46/62] Update changelog Fixes #135 --- CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 31e97333..db0e6f27 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +# 3.0.0 +* Dropped python 3.7 support + * If you still depend on python 3.7 use the 2.x version line +* Updated dependencies, most noticeably + * turbodbc to 4.x.y +* Update project setup/structure to pyproject.toml based project setup (poetry) +* Removed conda forge support + # 2.4.0 * Fixed bug when accessing underlying odbc connection while using NullPool based engine (Note: this addresses the superset [issue-20105](https://github.com/apache/superset/issues/20105)) From 0e9455c6b7e16cab84102debc7f3272b21718fac Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 09:50:19 +0200 Subject: [PATCH 47/62] Update minimum required python version in developer guide --- doc/developer_guide/developer_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/developer_guide/developer_guide.rst b/doc/developer_guide/developer_guide.rst index 7536796a..511a46f2 100644 --- a/doc/developer_guide/developer_guide.rst +++ b/doc/developer_guide/developer_guide.rst @@ -8,7 +8,7 @@ If you want to engage in development of this project you should have the followi Tools +++++ -* python_ >= 3.7 +* python_ >= 3.8 * git_ * Docker_ * integration-test-docker-environment_ From e5231dd9ed5299309ec98ce624c5ab3cac8995ee Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 10:20:52 +0200 Subject: [PATCH 48/62] Update developer guide --- doc/developer_guide/developer_guide.rst | 58 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/doc/developer_guide/developer_guide.rst b/doc/developer_guide/developer_guide.rst index 511a46f2..54819b04 100644 --- a/doc/developer_guide/developer_guide.rst +++ b/doc/developer_guide/developer_guide.rst @@ -9,6 +9,7 @@ If you want to engage in development of this project you should have the followi Tools +++++ * python_ >= 3.8 +* poetry_ >= 1.1.0 * git_ * Docker_ * integration-test-docker-environment_ @@ -61,6 +62,59 @@ Project Layout | ... +Setup Your Workspace +-------------------- + +Get The Source +++++++++++++++ + +.. code-block:: + + git clone https://github.com/exasol/sqlalchemy-exasol.git + +Setup the Tooling & Virtual Environment ++++++++++++++++++++++++++++++++++++++++ + +.. code-block:: + + poetry shell + poetry install + +.. warning:: + + make sure you have the poetry shell active whenever you want to work in the workspace + +Install the Git Commit Hooks +++++++++++++++++++++++++++++ + +.. code-block:: + + pre-commit install + +.. note:: + + This may need to be rerun if you want or do add non standard hook types, for further details + see `pre-commit install -h`. + + +Task Runner (Nox) +----------------- +Most repeating and complex tasks within this project are automated using the task runner `nox`. +To get an overview about the available `tasks` just run: + +.. code-block:: + + nox -l + +All task(s) which will be run by default will have a leading `*`. +In order to run a specific task execute the following command: + +.. code-block:: + + nox -s + +You can modify or add new task by editing the file `noxfile.py`. + Tests ----- @@ -68,7 +122,8 @@ Tests .. code-block:: - pip install -r requirements_dev.txt + # make sure you are using the virtual environment poetry has setup for this project + poetry shell #. Run all tests with `pyodbc` connector @@ -96,6 +151,7 @@ Tests .. _action: https://github.com/exasol/sqlalchemy_exasol/actions .. _python: https://www.python.org/ +.. _poetry: https://python-poetry.org/ .. _git: https://git-scm.com/ .. _Docker: https://www.docker.com/ .. _integration-test-docker-environment: https://github.com/exasol/integration-test-docker-environment From ee24d9a788b9f317be8bb41055eb6f0cd156a472 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 11:46:26 +0200 Subject: [PATCH 49/62] Add todo for updating turbodbc dependency --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 405feb57..c956db95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,8 @@ python = ">=3.8,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" packaging = "^21.3" +# TODO: replace once bugfix is published +# turbodbc = { version = ">=4.x.y", optional = true } turbodbc = {path = "../../Downloads/turbodbc-4.5.3.tar.gz"} [tool.poetry.dev-dependencies] From b6ed83cf32f1ade06f38de73feadf6fc8aa91085 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 11:56:53 +0200 Subject: [PATCH 50/62] Remove link check from test workflow --- .github/workflows/ci.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d940ab50..20f62085 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -62,9 +62,6 @@ jobs: ITDE_URL: "https://github.com/exasol/integration-test-docker-environment.git" ITDE_TAG: "0.10.0" - - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} - run: poetry run nox -s "check-links" - - name: Run Test for Python ${{ matrix.python }} using ${{ matrix.connector }} run: poetry run nox -s "verify(connector='${{ matrix.connector }}')" From beed934542208d9ecb338bd96cac59310f86131a Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 12:51:04 +0200 Subject: [PATCH 51/62] Update version check hook and script --- .pre-commit-config.yaml | 2 +- scripts/version_check.py | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff516453..53fb7fe1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: name: Check if version(s) are in sync always_run: true language: system - entry: python scripts/version_check.py sqlalchemy_exasol/version.py + entry: python scripts/version_check.py --fix sqlalchemy_exasol/version.py - repo: https://github.com/asottile/pyupgrade rev: v2.34.0 diff --git a/scripts/version_check.py b/scripts/version_check.py index cf395737..a41cc3c6 100644 --- a/scripts/version_check.py +++ b/scripts/version_check.py @@ -23,12 +23,14 @@ VERSION = f"{{MAJOR}}.{{MINOR}}.{{PATCH}}" ''') + "\n" + + # fmt: on def version_from_string(s): """Converts a version string of the following format major.minor.patch to a version object""" - major, minor, patch = [int(number, base=0) for number in s.split(".")] + major, minor, patch = (int(number, base=0) for number in s.split(".")) return Version(major, minor, patch) @@ -38,7 +40,7 @@ class CommitHookError(Exception): def version_from_python_module(path): """Retrieve version information from the `version` module""" - with open(path, "r") as file: + with open(path) as file: _locals, _globals = {}, {} exec(file.read(), _locals, _globals) @@ -56,8 +58,7 @@ def version_from_poetry(): raise CommitHookError("Couldn't find poetry executable") result = subprocess.run( - [poetry, "version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) + [poetry, "version"], capture_output=True) version = result.stdout.decode().split()[1] return version_from_string(version) @@ -87,11 +88,11 @@ def _create_parser(): help="enabled debug mode for execution.", ) parser.add_argument( - "-c", - "--check", + "-f", + "--fix", action="store_true", default=False, - help="check instead of update/fix.", + help="fix instead of check.", ) return parser @@ -102,16 +103,20 @@ def _main_debug(args): def are_versions_equal(lhs, rhs): return ( - lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch + lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch ) + if args.fix: + write_version_module(poetry_version, args.version_module) + if not are_versions_equal(module_version, poetry_version): print( f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!" ) - if not args.check: - write_version_module(poetry_version, args.version_module) + if args.fix: + print(f"Updating version in file ({args.version_module}) from {module_version} to {poetry_version}") return _FAILURE + return _SUCCESS From e00c99bfd4106e37e5c4006b10e7c53dbd5a7079 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 13:12:09 +0200 Subject: [PATCH 52/62] Remove link check from CI - CD workflow --- .github/workflows/ci-cd.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index df09c58d..edfaf8fc 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -61,9 +61,6 @@ jobs: ITDE_URL: "https://github.com/exasol/integration-test-docker-environment.git" ITDE_TAG: "0.10.0" - - name: Check documentation links ${{ matrix.python }} using ${{ matrix.connector }} - run: poetry run nox -s "check-links" - - name: Run Test for Python ${{ matrix.python }} using ${{ matrix.connector }} run: poetry run nox -s "verify(connector='${{ matrix.connector }}')" From 54f1a5f073902fb2c080719e18dacb59c0c49710 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 14:03:02 +0200 Subject: [PATCH 53/62] Add git script/module to query available tags --- scripts/git.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 scripts/git.py diff --git a/scripts/git.py b/scripts/git.py new file mode 100644 index 00000000..6d73ebb1 --- /dev/null +++ b/scripts/git.py @@ -0,0 +1,15 @@ +from subprocess import PIPE, run + + +def tags(): + """ + Returns a list of all tags, sorted from [0] oldest to [-1] newest. + PreConditions: + - the git cli tool needs to be installed + - the git cli tool can be found via $PATH + - the code is executed where the working directory is within a git repository + """ + command = ["git", "tag", "--sort=committerdate"] + result = run(command, capture_output=True, check=True) + tags = (tag.strip() for tag in result.stdout.decode("utf-8").splitlines()) + return list(tags) From 1681f93158024c335680a42c4bcb5090b47fce5e Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Thu, 7 Jul 2022 15:51:13 +0200 Subject: [PATCH 54/62] Add release support for new project format to noxfile and CI/CD --- .github/workflows/ci-cd.yml | 7 ++--- noxfile.py | 56 +++++++++++++++++++++++++++++++------ scripts/version_check.py | 14 ++++------ 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index edfaf8fc..19c95b44 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -92,8 +92,5 @@ jobs: with: poetry-version: 1.1.13 - - name: Build sdist and wheel packages - run: poetry build - - - name: Push package to PYPI - run: poetry publish --username=__token__ --password=${{ secrets.pypi_token }} + - name: Build and push package to PYPI + run: poetry run nox -s release -- --username=__token__ --password=${{ secrets.pypi_token }} diff --git a/noxfile.py b/noxfile.py index 1fe70229..e544df2e 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,5 +1,6 @@ import os import sys +from argparse import ArgumentParser from contextlib import contextmanager from pathlib import Path from tempfile import TemporaryDirectory @@ -11,10 +12,12 @@ sys.path.append(f"{SCRIPTS}") import nox +from git import tags from links import check as _check from links import documentation as _documentation from links import urls as _urls from pyodbc import connect +from version_check import version_from_poetry, version_from_python_module, version_from_string # default actions to be run if nothing is explicitly specified with the -s option nox.options.sessions = ["verify(connector='pyodbc')"] @@ -83,20 +86,57 @@ def temporary_odbc_config(config): @contextmanager def odbcconfig(): with temporary_odbc_config( - ODBCINST_INI_TEMPLATE.format(driver=Settings.ODBC_DRIVER) + ODBCINST_INI_TEMPLATE.format(driver=Settings.ODBC_DRIVER) ) as cfg: env_vars = {"ODBCSYSINI": f"{cfg.parent.resolve()}"} with environment(env_vars) as env: yield cfg, env -@nox.session(name="check-version", reuse_venv=True) -def check_version(session): +@nox.session(python=False) +def release(session: nox.Session): + def create_parser(): + p = ArgumentParser( + "Release a pypi package", + usage="nox -s release -- [-h] [-d] [-l LOGIN] [-p PASSWORD]", + ) + p.add_argument("-d", "--dry-run", action="store_true", help="just do a dry run") + p.add_argument("-u", "--username", help="pypi login/username") + p.add_argument("-p", "--password", help="password/token for the pypi account") + return p + + args = [] + parser = create_parser() + cli_args = parser.parse_args(session.posargs) + if cli_args.dry_run: + args.append("--dry-run") + if cli_args.username: + args.append("--username") + args.append(cli_args.username) + if cli_args.password: + args.append("--password") + args.append(cli_args.password) + + version_file = version_from_python_module(PROJECT_ROOT / 'sqlalchemy_exasol' / 'version.py') + module_version = version_from_poetry() + git_version = version_from_string(tags()[-1]) + + if not (module_version == git_version == version_file): + session.error( + f"Versions out of sync, version file: {version_file}, poetry: {module_version}, tag: {git_version}." + ) + + session.run( + "poetry", + "build", + external=True, + ) + session.run( - "python", - f"{SCRIPTS / 'version_check.py'}", - "--check", - f"{PROJECT_ROOT / 'sqlalchemy_exasol' / 'version.py'}", + "poetry", + "publish", + *args, + external=True, ) @@ -242,7 +282,7 @@ def check_links(session): if errors: session.error( "\n" - + "\n".join((f"Url: {e[1]}, File: {e[0]}, Error: {e[3]}" for e in errors)) + + "\n".join(f"Url: {e[1]}, File: {e[0]}, Error: {e[3]}" for e in errors) ) diff --git a/scripts/version_check.py b/scripts/version_check.py index a41cc3c6..84ade4c5 100644 --- a/scripts/version_check.py +++ b/scripts/version_check.py @@ -57,8 +57,7 @@ def version_from_poetry(): if not poetry: raise CommitHookError("Couldn't find poetry executable") - result = subprocess.run( - [poetry, "version"], capture_output=True) + result = subprocess.run([poetry, "version"], capture_output=True) version = result.stdout.decode().split()[1] return version_from_string(version) @@ -101,20 +100,17 @@ def _main_debug(args): module_version = version_from_python_module(args.version_module) poetry_version = version_from_poetry() - def are_versions_equal(lhs, rhs): - return ( - lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch - ) - if args.fix: write_version_module(poetry_version, args.version_module) - if not are_versions_equal(module_version, poetry_version): + if not module_version == poetry_version: print( f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!" ) if args.fix: - print(f"Updating version in file ({args.version_module}) from {module_version} to {poetry_version}") + print( + f"Updating version in file ({args.version_module}) from {module_version} to {poetry_version}" + ) return _FAILURE return _SUCCESS From 7b18c2b3ed505a50881bad4c911138784dadbc2d Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 12 Jul 2022 08:30:00 +0200 Subject: [PATCH 55/62] Prepare 3.0.0 release --- .github/workflows/ci-cd.yml | 7 ++++++- .github/workflows/ci.yaml | 7 ++++++- CHANGES.md | 9 +++++++-- poetry.lock | 37 ++++++------------------------------- pyproject.toml | 7 ++++--- 5 files changed, 29 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 19c95b44..6c455d9e 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -19,7 +19,12 @@ jobs: - "3.10" connector: - pyodbc - - turbodbc + # TODO: Reenable once the issue(s) below have been fixed. + # Turbodbc can't be supported using poetry until: + # - https://github.com/blue-yonder/turbodbc/issues/358 + # - https://github.com/exasol/sqlalchemy-exasol/issues/146 + # are fixed. + # - turbodbc exasol_version: - 7.1.6 - 7.0.16 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 20f62085..06c064bd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,7 +23,12 @@ jobs: - "3.10" connector: - pyodbc - - turbodbc + # TODO: Reenable once the issue(s) below have been fixed. + # Turbodbc can't be supported using poetry until: + # - https://github.com/blue-yonder/turbodbc/issues/358 + # - https://github.com/exasol/sqlalchemy-exasol/issues/146 + # are fixed. + # - turbodbc exasol_version: - 7.1.6 - 7.0.16 diff --git a/CHANGES.md b/CHANGES.md index db0e6f27..8c5cf1ca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,13 @@ # 3.0.0 +⚠️ ATTENTION ⚠️ + * The support of the turbodbc feature have been suspended, until the following issues have been addressed + * https://github.com/blue-yonder/turbodbc/issues/358 + * https://github.com/exasol/sqlalchemy-exasol/issues/146 + +Note: If you depend on turbodbc we suggest you to use the latest version supporting it (2.4.0) + * Dropped python 3.7 support * If you still depend on python 3.7 use the 2.x version line -* Updated dependencies, most noticeably - * turbodbc to 4.x.y * Update project setup/structure to pyproject.toml based project setup (poetry) * Removed conda forge support diff --git a/poetry.lock b/poetry.lock index 5d9802fb..6cea9d36 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,7 +11,7 @@ test = ["coverage", "flake8", "pexpect", "wheel"] [[package]] name = "atomicwrites" -version = "1.4.0" +version = "1.4.1" description = "Atomic file writes." category = "dev" optional = false @@ -176,7 +176,7 @@ dev = ["pre-commit", "tox"] [[package]] name = "pre-commit" -version = "2.19.0" +version = "2.20.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -329,22 +329,6 @@ category = "dev" optional = false python-versions = ">=3.7" -[[package]] -name = "turbodbc" -version = "4.5.3" -description = "turbodbc is a Python DB API 2.0 compatible ODBC driver" -category = "main" -optional = false -python-versions = ">=3.8" - -[package.extras] -arrow = ["pyarrow (>=1.0,<7.1.0)"] -numpy = ["numpy (>=1.19.0)"] - -[package.source] -type = "file" -url = "../../Downloads/turbodbc-4.5.3.tar.gz" - [[package]] name = "urlscan" version = "0.9.9" @@ -391,22 +375,19 @@ optional = false python-versions = "*" [extras] -turbodbc = ["turbodbc"] +turbodbc = [] [metadata] lock-version = "1.1" python-versions = ">=3.8,<4.0" -content-hash = "bbe001e6f23ed11f269f8b7b9a0f79353016a662a7fec78095b27f14dab55192" +content-hash = "af943c60ce6120fc8df504dc8b20d0e3632ecfc2d781adb1a7656c5b9cac6a81" [metadata.files] argcomplete = [ {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, ] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] +atomicwrites = [] attrs = [ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, @@ -502,10 +483,7 @@ pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] -pre-commit = [ - {file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"}, - {file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"}, -] +pre-commit = [] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -628,9 +606,6 @@ tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -turbodbc = [ - {file = "turbodbc-4.5.3.tar.gz", hash = "sha256:72b78689bfa9f34c22bae6c7795b801da134c6fcb329101b3b690c0a79beb439"}, -] urlscan = [ {file = "urlscan-0.9.9-py3-none-any.whl", hash = "sha256:864f5332520f4fafe67d68e023aefc5636993cedb69145e4d9bb3a2884ee34ed"}, {file = "urlscan-0.9.9.tar.gz", hash = "sha256:da66b99b3364f97d11ecfc105b8c95dd155bd08d8313dd9cc6472791493480d1"}, diff --git a/pyproject.toml b/pyproject.toml index c956db95..05ff8b17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,9 +56,10 @@ python = ">=3.8,<4.0" SQLAlchemy = ">=1.3.24,<1.4" pyodbc = ">=4.0.32" packaging = "^21.3" -# TODO: replace once bugfix is published -# turbodbc = { version = ">=4.x.y", optional = true } -turbodbc = {path = "../../Downloads/turbodbc-4.5.3.tar.gz"} +# TODO: Reenable once the causing issues got fixed: +# - https://github.com/blue-yonder/turbodbc/issues/358 +# - https://github.com/exasol/sqlalchemy-exasol/issues/146 +# turbodbc = { version = ">4.5.3", optional = true } [tool.poetry.dev-dependencies] nox = ">=2022.1.7" From 6d9135c58442a67d968530600d7fc6cb9d635c35 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 12 Jul 2022 08:50:54 +0200 Subject: [PATCH 56/62] Fix missing check in verify step --- noxfile.py | 114 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/noxfile.py b/noxfile.py index e544df2e..fc817bb2 100644 --- a/noxfile.py +++ b/noxfile.py @@ -17,7 +17,11 @@ from links import documentation as _documentation from links import urls as _urls from pyodbc import connect -from version_check import version_from_poetry, version_from_python_module, version_from_string +from version_check import ( + version_from_poetry, + version_from_python_module, + version_from_string, +) # default actions to be run if nothing is explicitly specified with the -s option nox.options.sessions = ["verify(connector='pyodbc')"] @@ -30,6 +34,7 @@ class Settings: ENVIRONMENT_NAME = "test" DB_PORT = 8888 BUCKETFS_PORT = 6666 + VERSION_FILE = PROJECT_ROOT / "sqlalchemy_exasol" / "version.py" ODBCINST_INI_TEMPLATE = dedent( @@ -93,58 +98,22 @@ def odbcconfig(): yield cfg, env -@nox.session(python=False) -def release(session: nox.Session): - def create_parser(): - p = ArgumentParser( - "Release a pypi package", - usage="nox -s release -- [-h] [-d] [-l LOGIN] [-p PASSWORD]", - ) - p.add_argument("-d", "--dry-run", action="store_true", help="just do a dry run") - p.add_argument("-u", "--username", help="pypi login/username") - p.add_argument("-p", "--password", help="password/token for the pypi account") - return p - - args = [] - parser = create_parser() - cli_args = parser.parse_args(session.posargs) - if cli_args.dry_run: - args.append("--dry-run") - if cli_args.username: - args.append("--username") - args.append(cli_args.username) - if cli_args.password: - args.append("--password") - args.append(cli_args.password) - - version_file = version_from_python_module(PROJECT_ROOT / 'sqlalchemy_exasol' / 'version.py') - module_version = version_from_poetry() - git_version = version_from_string(tags()[-1]) - - if not (module_version == git_version == version_file): - session.error( - f"Versions out of sync, version file: {version_file}, poetry: {module_version}, tag: {git_version}." - ) - - session.run( - "poetry", - "build", - external=True, - ) - - session.run( - "poetry", - "publish", - *args, - external=True, - ) - - @nox.session @nox.parametrize("connector", Settings.CONNECTORS) def verify(session, connector): """Prepare and run all available tests""" - session.notify(find_session_runner(session, "check-version")) + + def is_version_in_sync(): + return ( + version_from_python_module(Settings.VERSION_FILE) == version_from_poetry() + ) + + if not is_version_in_sync(): + session.error( + "Versions out of sync, version file:" + f"{version_from_python_module(Settings.VERSION_FILE)}," + f"poetry: {version_from_poetry()}." + ) session.notify(find_session_runner(session, "db-start")) session.notify( find_session_runner(session, f"integration(connector='{connector}')") @@ -291,3 +260,50 @@ def list_links(session): """List all links within the documentation""" for path, url in _urls(_documentation(PROJECT_ROOT)): session.log(f"Url: {url}, File: {path}") + + +@nox.session(python=False) +def release(session: nox.Session): + def create_parser(): + p = ArgumentParser( + "Release a pypi package", + usage="nox -s release -- [-h] [-d] [-l LOGIN] [-p PASSWORD]", + ) + p.add_argument("-d", "--dry-run", action="store_true", help="just do a dry run") + p.add_argument("-u", "--username", help="pypi login/username") + p.add_argument("-p", "--password", help="password/token for the pypi account") + return p + + args = [] + parser = create_parser() + cli_args = parser.parse_args(session.posargs) + if cli_args.dry_run: + args.append("--dry-run") + if cli_args.username: + args.append("--username") + args.append(cli_args.username) + if cli_args.password: + args.append("--password") + args.append(cli_args.password) + + version_file = version_from_python_module(Settings.VERSION_FILE) + module_version = version_from_poetry() + git_version = version_from_string(tags()[-1]) + + if not (module_version == git_version == version_file): + session.error( + f"Versions out of sync, version file: {version_file}, poetry: {module_version}, tag: {git_version}." + ) + + session.run( + "poetry", + "build", + external=True, + ) + + session.run( + "poetry", + "publish", + *args, + external=True, + ) From 397bfaa65842908d367c700be84f0ecefc025b02 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 12 Jul 2022 09:06:07 +0200 Subject: [PATCH 57/62] Make sure no unnecessary virtual environments will be created --- TODOs.txt | 7 +++++++ noxfile.py | 14 +++++++------- odbcconfig/odbcinst.ini | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 TODOs.txt diff --git a/TODOs.txt b/TODOs.txt new file mode 100644 index 00000000..a1f0df32 --- /dev/null +++ b/TODOs.txt @@ -0,0 +1,7 @@ +FINAL TASKS: +------------ +* ATTENTION: Update turbodbc driver to latest including installation fix! +* make sure automated publish via GH action still works with poetry +* CLOSE: https://github.com/exasol/sqlalchemy-exasol/issues/135 +* CLOSE: https://github.com/exasol/sqlalchemy-exasol/issues/146 +* CLOSE: https://github.com/exasol/sqlalchemy-exasol/issues/128 diff --git a/noxfile.py b/noxfile.py index fc817bb2..6f840101 100644 --- a/noxfile.py +++ b/noxfile.py @@ -98,7 +98,7 @@ def odbcconfig(): yield cfg, env -@nox.session +@nox.session(python=False) @nox.parametrize("connector", Settings.CONNECTORS) def verify(session, connector): """Prepare and run all available tests""" @@ -121,7 +121,7 @@ def is_version_in_sync(): session.notify(find_session_runner(session, "db-stop")) -@nox.session(name="db-start", reuse_venv=True) +@nox.session(name="db-start", python=False) def start_db(session): """Start the test database""" @@ -174,14 +174,14 @@ def populate(): populate() -@nox.session(name="db-stop", reuse_venv=True) +@nox.session(name="db-stop", python=False) def stop_db(session): """Stop the test database""" session.run("docker", "kill", "db_container_test", external=True) session.run("docker", "kill", "test_container_test", external=True) -@nox.session +@nox.session(python=False) @nox.parametrize("connector", Settings.CONNECTORS) def integration(session, connector): """Run(s) the integration tests for a specific connector. Expects a test database to be available.""" @@ -197,7 +197,7 @@ def integration(session, connector): session.run("pytest", "--dropfirst", "--dburi", uri, external=True, env=env) -@nox.session(name="report-skipped", python=None) +@nox.session(name="report-skipped", python=False) def report_skipped(session): """ Runs all tests for all supported connectors and creates a csv report of skipped tests for each connector. @@ -239,7 +239,7 @@ def report_skipped(session): ) -@nox.session(name="check-links", python=None) +@nox.session(name="check-links", python=False) def check_links(session): """Checks weather or not all links in the documentation can be accessed""" errors = [] @@ -255,7 +255,7 @@ def check_links(session): ) -@nox.session(name="list-links", python=None) +@nox.session(name="list-links", python=False) def list_links(session): """List all links within the documentation""" for path, url in _urls(_documentation(PROJECT_ROOT)): diff --git a/odbcconfig/odbcinst.ini b/odbcconfig/odbcinst.ini index 7769ff75..e676317a 100644 --- a/odbcconfig/odbcinst.ini +++ b/odbcconfig/odbcinst.ini @@ -4,4 +4,4 @@ [EXAODBC] #Driver location will be appended in build environment: -#DRIVER= +DRIVER=/home/nic/Projects/sqlalchemy-exasol/driver/libexaodbc-uo2214lv1.so From e7dd1f7548c9c7c413aea724719242173c59010d Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 12 Jul 2022 15:23:50 +0200 Subject: [PATCH 58/62] Update pytest dependency --- poetry.lock | 57 +++++++++++++++++++------------------------------- pyproject.toml | 9 +++++++- setup.cfg | 8 ------- 3 files changed, 29 insertions(+), 45 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6cea9d36..bbe8d8df 100644 --- a/poetry.lock +++ b/poetry.lock @@ -107,12 +107,12 @@ python-versions = ">=3.7" license = ["ukkonen"] [[package]] -name = "more-itertools" -version = "8.13.0" -description = "More routines for operating on iterables, beyond itertools" +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = "*" [[package]] name = "nodeenv" @@ -165,14 +165,15 @@ test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytes [[package]] name = "pluggy" -version = "0.13.1" +version = "1.0.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.extras] dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" @@ -219,24 +220,23 @@ diagrams = ["railroad-diagrams", "jinja2"] [[package]] name = "pytest" -version = "5.4.3" +version = "6.2.5" description = "pytest: simple powerful testing with Python" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=17.4.0" +attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -more-itertools = ">=4.0.0" +iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<1.0" -py = ">=1.5.0" -wcwidth = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" [package.extras] -checkqa-mypy = ["mypy (==v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] @@ -366,21 +366,13 @@ six = ">=1.9.0,<2" docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] -[[package]] -name = "wcwidth" -version = "0.2.5" -description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" -optional = false -python-versions = "*" - [extras] turbodbc = [] [metadata] lock-version = "1.1" python-versions = ">=3.8,<4.0" -content-hash = "af943c60ce6120fc8df504dc8b20d0e3632ecfc2d781adb1a7656c5b9cac6a81" +content-hash = "cddd429ac7f7bad772b7e0204605e2d231891085392a3c98e9e0e6a70b2896a7" [metadata.files] argcomplete = [ @@ -459,9 +451,9 @@ identify = [ {file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"}, {file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"}, ] -more-itertools = [ - {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, - {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] nodeenv = [ {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, @@ -480,8 +472,8 @@ platformdirs = [ {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] pre-commit = [] py = [ @@ -507,10 +499,7 @@ pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] -pytest = [ - {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, - {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, -] +pytest = [] pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, @@ -617,7 +606,3 @@ virtualenv = [ {file = "virtualenv-20.15.1-py2.py3-none-any.whl", hash = "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf"}, {file = "virtualenv-20.15.1.tar.gz", hash = "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4"}, ] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] diff --git a/pyproject.toml b/pyproject.toml index 05ff8b17..711dde3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ urlscan = ">=0.9.9" pytest-json-report = ">=1.5.0" # The excluded versions mirror the excluded versions of sqla 1.3.X. # The limitation/issue pytest <6 is tracked in https://github.com/exasol/sqlalchemy-exasol/issues/144 -pytest = ">=3.1.0,!=3.9.1,!=3.9.2,<6" +pytest = ">=6.0.0,<7" pytest-cov = ">=2.7.0" pre-commit = "^2.19.0" wheel = "^0.37.1" @@ -78,3 +78,10 @@ turbodbc = ["turbodbc"] [tool.poetry.plugins."sqlalchemy.dialects"] "exa.pyodbc" = "sqlalchemy_exasol.pyodbc:EXADialect_pyodbc" "exa.turbodbc" = "sqlalchemy_exasol.turbodbc:EXADialect_turbodbc" + +[tool.pytest.ini_options] +addopts= "--tb native -v -r fxX" +python_files= "test/*test_*.py" +filterwarnings = [ + "ignore::DeprecationWarning" +] diff --git a/setup.cfg b/setup.cfg index f2400ca2..bb0aea60 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,11 +1,3 @@ -# pyproject.toml based configuration is supported starting with pytest >= 6 -# see https://github.com/exasol/sqlalchemy-exasol/issues/144 -[tool:pytest] -addopts= --tb native -v -r fxX -python_files=test/*test_*.py -filterwarnings = - error::DeprecationWarning - [sqla_testing] requirement_cls=sqlalchemy_exasol.requirements:Requirements profile_file=.profiles.txt From a28c9465801c1b3c06821e221c29aac389e03acc Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 12 Jul 2022 16:44:59 +0200 Subject: [PATCH 59/62] Address pytest compatibility issue --- poetry.lock | 57 +++++++------------------------------------------- pyproject.toml | 7 ++++--- 2 files changed, 11 insertions(+), 53 deletions(-) diff --git a/poetry.lock b/poetry.lock index bbe8d8df..7b3d597d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -63,7 +63,7 @@ development = ["black", "flake8", "mypy", "pytest", "types-colorama"] [[package]] name = "coverage" -version = "6.4.1" +version = "6.4.2" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -165,15 +165,14 @@ test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytes [[package]] name = "pluggy" -version = "1.0.0" +version = "0.13.1" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" @@ -372,7 +371,7 @@ turbodbc = [] [metadata] lock-version = "1.1" python-versions = ">=3.8,<4.0" -content-hash = "cddd429ac7f7bad772b7e0204605e2d231891085392a3c98e9e0e6a70b2896a7" +content-hash = "20a4b8a3436e8ec9db41a1493e8c5c384e2143f37824acf519f18d184634319e" [metadata.files] argcomplete = [ @@ -396,49 +395,7 @@ colorlog = [ {file = "colorlog-6.6.0-py2.py3-none-any.whl", hash = "sha256:351c51e866c86c3217f08e4b067a7974a678be78f07f85fc2d55b8babde6d94e"}, {file = "colorlog-6.6.0.tar.gz", hash = "sha256:344f73204009e4c83c5b6beb00b3c45dc70fcdae3c80db919e0a4171d006fde8"}, ] -coverage = [ - {file = "coverage-6.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b"}, - {file = "coverage-6.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4"}, - {file = "coverage-6.4.1-cp310-cp310-win32.whl", hash = "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df"}, - {file = "coverage-6.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6"}, - {file = "coverage-6.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6"}, - {file = "coverage-6.4.1-cp37-cp37m-win32.whl", hash = "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e"}, - {file = "coverage-6.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28"}, - {file = "coverage-6.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54"}, - {file = "coverage-6.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83"}, - {file = "coverage-6.4.1-cp38-cp38-win32.whl", hash = "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b"}, - {file = "coverage-6.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c"}, - {file = "coverage-6.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df"}, - {file = "coverage-6.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264"}, - {file = "coverage-6.4.1-cp39-cp39-win32.whl", hash = "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9"}, - {file = "coverage-6.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397"}, - {file = "coverage-6.4.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815"}, - {file = "coverage-6.4.1.tar.gz", hash = "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c"}, -] +coverage = [] distlib = [ {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, @@ -472,8 +429,8 @@ platformdirs = [ {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] pre-commit = [] py = [ diff --git a/pyproject.toml b/pyproject.toml index 711dde3f..9fa583b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,9 +23,9 @@ classifiers = [ "License :: OSI Approved :: BSD License", "Programming Language :: SQL", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Topic :: Database", "Topic :: Software Development", "Topic :: Software Development :: Libraries", @@ -67,7 +67,7 @@ urlscan = ">=0.9.9" pytest-json-report = ">=1.5.0" # The excluded versions mirror the excluded versions of sqla 1.3.X. # The limitation/issue pytest <6 is tracked in https://github.com/exasol/sqlalchemy-exasol/issues/144 -pytest = ">=6.0.0,<7" +pytest = ">=6,<7" pytest-cov = ">=2.7.0" pre-commit = "^2.19.0" wheel = "^0.37.1" @@ -83,5 +83,6 @@ turbodbc = ["turbodbc"] addopts= "--tb native -v -r fxX" python_files= "test/*test_*.py" filterwarnings = [ - "ignore::DeprecationWarning" + "error::DeprecationWarning", + "ignore::DeprecationWarning:sqlalchemy.testing.plugin.*", ] From 835647a08047a88c625d8b5430dfa985ada24118 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 13 Jul 2022 08:42:08 +0200 Subject: [PATCH 60/62] Adjust release task and action --- .github/workflows/ci-cd.yml | 2 +- noxfile.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 6c455d9e..2b0a0cc4 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -98,4 +98,4 @@ jobs: poetry-version: 1.1.13 - name: Build and push package to PYPI - run: poetry run nox -s release -- --username=__token__ --password=${{ secrets.pypi_token }} + run: POETRY_PYPI_TOKEN_PYPI="${{ secrets.pypi_token }}" poetry run nox -s release diff --git a/noxfile.py b/noxfile.py index 6f840101..b58311d3 100644 --- a/noxfile.py +++ b/noxfile.py @@ -267,11 +267,10 @@ def release(session: nox.Session): def create_parser(): p = ArgumentParser( "Release a pypi package", - usage="nox -s release -- [-h] [-d] [-l LOGIN] [-p PASSWORD]", + usage="nox -s release -- [-h] [-d] [-l LOGIN]", ) p.add_argument("-d", "--dry-run", action="store_true", help="just do a dry run") p.add_argument("-u", "--username", help="pypi login/username") - p.add_argument("-p", "--password", help="password/token for the pypi account") return p args = [] @@ -282,9 +281,6 @@ def create_parser(): if cli_args.username: args.append("--username") args.append(cli_args.username) - if cli_args.password: - args.append("--password") - args.append(cli_args.password) version_file = version_from_python_module(Settings.VERSION_FILE) module_version = version_from_poetry() From 3e1f1969f7a82e129db900665fb8ebb5513a3fab Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 13 Jul 2022 08:59:59 +0200 Subject: [PATCH 61/62] Remove odbcinst.ini and replace with template --- .gitignore | 2 ++ odbcconfig/odbcinst.ini | 7 ------- odbcconfig/odbcinst.ini.template | 7 +++++++ 3 files changed, 9 insertions(+), 7 deletions(-) delete mode 100644 odbcconfig/odbcinst.ini create mode 100644 odbcconfig/odbcinst.ini.template diff --git a/.gitignore b/.gitignore index 31c17298..34ab2a6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +odbcconfig/odbcinst.ini + *.py[cod] .build_output diff --git a/odbcconfig/odbcinst.ini b/odbcconfig/odbcinst.ini deleted file mode 100644 index e676317a..00000000 --- a/odbcconfig/odbcinst.ini +++ /dev/null @@ -1,7 +0,0 @@ -[ODBC] -#Trace=yes -#TraceFile=~/odbc.trace - -[EXAODBC] -#Driver location will be appended in build environment: -DRIVER=/home/nic/Projects/sqlalchemy-exasol/driver/libexaodbc-uo2214lv1.so diff --git a/odbcconfig/odbcinst.ini.template b/odbcconfig/odbcinst.ini.template new file mode 100644 index 00000000..1e259a6a --- /dev/null +++ b/odbcconfig/odbcinst.ini.template @@ -0,0 +1,7 @@ +[ODBC] +#Trace=yes +#TraceFile=~/odbc.trace + +[EXAODBC] +#Driver location needs to be added in build environment: +DRIVER= From 95d77a90182e12148883973d70223b9c56aa3a9a Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Wed, 13 Jul 2022 15:53:12 +0200 Subject: [PATCH 62/62] Harden relase mechanism Either use environment variables for credentials if available, otherwise to fallback to interactivly asking for the credentials. --- .github/workflows/ci-cd.yml | 5 ++++- noxfile.py | 6 +----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2b0a0cc4..863cff43 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -98,4 +98,7 @@ jobs: poetry-version: 1.1.13 - name: Build and push package to PYPI - run: POETRY_PYPI_TOKEN_PYPI="${{ secrets.pypi_token }}" poetry run nox -s release + env: + POETRY_HTTP_BASIC_TEST_USERNAME: "__token__" + POETRY_HTTP_BASIC_TEST_PASSWORD: "${{ secrets.pypi_token }}" + run: poetry run nox -s release diff --git a/noxfile.py b/noxfile.py index b58311d3..7660237b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -267,10 +267,9 @@ def release(session: nox.Session): def create_parser(): p = ArgumentParser( "Release a pypi package", - usage="nox -s release -- [-h] [-d] [-l LOGIN]", + usage="nox -s release -- [-h] [-d]", ) p.add_argument("-d", "--dry-run", action="store_true", help="just do a dry run") - p.add_argument("-u", "--username", help="pypi login/username") return p args = [] @@ -278,9 +277,6 @@ def create_parser(): cli_args = parser.parse_args(session.posargs) if cli_args.dry_run: args.append("--dry-run") - if cli_args.username: - args.append("--username") - args.append(cli_args.username) version_file = version_from_python_module(Settings.VERSION_FILE) module_version = version_from_poetry()