Skip to content

Commit

Permalink
Merge pull request #27 from sot/ruff
Browse files Browse the repository at this point in the history
Ruff
  • Loading branch information
jeanconn authored Dec 18, 2024
2 parents 2ccddf0 + 9a606aa commit 37e1fa7
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 114 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/python-formatting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: check format using ruff
on: [push]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: chartboost/ruff-action@v1
with:
args: format --check
8 changes: 8 additions & 0 deletions .github/workflows/python-linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: lint code using ruff
on: [push]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: chartboost/ruff-action@v1
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.8.3
hooks:
# Run the linter.
- id: ruff
# Run the formatter.
- id: ruff-format
61 changes: 61 additions & 0 deletions ruff-base.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copied originally from pandas. This config requires ruff >= 0.2.
target-version = "py311"

# fix = true
lint.unfixable = []

lint.select = [
"I", # isort
"F", # pyflakes
"E", "W", # pycodestyle
"YTT", # flake8-2020
"B", # flake8-bugbear
"Q", # flake8-quotes
"T10", # flake8-debugger
"INT", # flake8-gettext
"PLC", "PLE", "PLR", "PLW", # pylint
"PIE", # misc lints
"PYI", # flake8-pyi
"TID", # tidy imports
"ISC", # implicit string concatenation
"TCH", # type-checking imports
"C4", # comprehensions
"PGH" # pygrep-hooks
]

# Some additional rules that are useful
lint.extend-select = [
"UP009", # UTF-8 encoding declaration is unnecessary
"SIM118", # Use `key in dict` instead of `key in dict.keys()`
"D205", # One blank line required between summary line and description
"ARG001", # Unused function argument
"RSE102", # Unnecessary parentheses on raised exception
"PERF401", # Use a list comprehension to create a transformed list
"S101", # Use of `assert` detected
]

lint.ignore = [
"ISC001", # Disable this for compatibility with ruff format
"E402", # module level import not at top of file
"E731", # do not assign a lambda expression, use a def
"PLR2004", # Magic number
"B028", # No explicit `stacklevel` keyword argument found
"PLR0913", # Too many arguments to function call
"PLR1730", # Checks for if statements that can be replaced with min() or max() calls
]

extend-exclude = [
"docs",
]

[lint.pycodestyle]
max-line-length = 100 # E501 reports lines that exceed the length of 100.

[lint.extend-per-file-ignores]
"__init__.py" = ["E402", "F401", "F403"]
# For tests:
# - D205: Don't worry about test docstrings
# - ARG001: Unused function argument false positives for some fixtures
# - E501: Line-too-long
# - S101: Do not use assert
"**/tests/test_*.py" = ["D205", "ARG001", "E501", "S101"]
25 changes: 25 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
extend = "ruff-base.toml"

# These are files to exclude for this project.
extend-exclude = [
# "**/*.ipynb", # commonly not ruff-compliant
]

# These are rules that commonly cause many ruff warnings. Code will be improved by
# incrementally fixing code to adhere to these rules, but for practical purposes they
# can be ignored by uncommenting each one. You can also add to this list as needed.
lint.extend-ignore = [
# "B905", # `zip()` without an explicit `strict=` parameter
# "PLC1901", # compare-to-empty-string
# "PLR0911", # Too many returns
# "PLR0912", # Too many branches
# "PLR0915", # Too many statements
# "PGH004", # Use specific rule codes when using `noqa`
# "C401", # Unnecessary generator (rewrite as a `set` comprehension)
# "C402", # Unnecessary generator (rewrite as a dict comprehension)
# "C405", # Unnecessary `list` literal (rewrite as a `set` literal)
# "C408", # Unnecessary `dict` call (rewrite as a literal)
# "C416", # Unnecessary `dict` comprehension (rewrite using `dict()`)
# "G010", # warn is deprecated in favor of warning
# "PYI056", # Calling `.append()` on `__all__` may not be supported by all type checkers
]
31 changes: 16 additions & 15 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from setuptools import setup
from testr.setup_helper import cmdclass
from ska_helpers.setup_helper import duplicate_package_info
from testr.setup_helper import cmdclass

name = "ska_dbi"
namespace = "Ska.DBI"

packages = ["ska_dbi", "ska_dbi.tests"]
package_dir = {name: name}
package_data = {'ska_dbi.tests': ['ska_dbi_test_table.sql']}
package_data = {"ska_dbi.tests": ["ska_dbi_test_table.sql"]}

duplicate_package_info(packages, name, namespace)
duplicate_package_info(package_dir, name, namespace)
duplicate_package_info(package_data, name, namespace)

setup(name=name,
author='Tom Aldcroft',
description='Database interface utilities',
author_email='taldcroft@cfa.harvard.edu',
use_scm_version=True,
setup_requires=['setuptools_scm', 'setuptools_scm_git_archive'],
zip_safe=False,
package_dir=package_dir,
packages=packages,
package_data=package_data,
tests_require=['pytest'],
cmdclass=cmdclass,
)
setup(
name=name,
author="Tom Aldcroft",
description="Database interface utilities",
author_email="taldcroft@cfa.harvard.edu",
use_scm_version=True,
setup_requires=["setuptools_scm", "setuptools_scm_git_archive"],
zip_safe=False,
package_dir=package_dir,
packages=packages,
package_data=package_data,
tests_require=["pytest"],
cmdclass=cmdclass,
)
68 changes: 44 additions & 24 deletions ska_dbi/DBI.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
ska_dbi provides simple methods for database access and data insertion.
Features:
- Sqlite connections are supported.
- Integration with numpy record arrays.
- Verbose mode to show transaction information.
"""
import os
import sys

import sqlite3 as dbapi2
from ska_dbi.common import DEFAULT_CONFIG, NoPasswordError

from ska_dbi.common import DEFAULT_CONFIG


def _denumpy(x):
"""
Convert from numpy type to native python type.
Try using the numpy.tolist() to convert to native python type.
DBI's can't typically handle numpy vals."""
try:
return x.tolist()
except:
except Exception:
return x


Expand All @@ -41,22 +44,29 @@ class DBI(object):
:rtype: DBI object
"""
def __init__(self, dbi=None, server=None,
numpy=True, autocommit=True, verbose=False,
**kwargs):


if dbi != 'sqlite':
raise ValueError(f'ska_dbi.DBI only supports sqlite at this time. Got {dbi}.')
def __init__(
self,
dbi=None,
server=None,
numpy=True,
autocommit=True,
verbose=False,
**kwargs,
):
if dbi != "sqlite":
raise ValueError(
f"ska_dbi.DBI only supports sqlite at this time. Got {dbi}."
)

self.dbi = dbi
self.server = server or DEFAULT_CONFIG[dbi].get('server')
self.server = server or DEFAULT_CONFIG[dbi].get("server")
self.numpy = numpy
self.autocommit = autocommit
self.verbose = verbose

if self.verbose:
print('Connecting to', self.dbi, 'server', self.server)
print("Connecting to", self.dbi, "server", self.server)

self.conn = dbapi2.connect(self.server)
self.Error = dbapi2.Error
Expand Down Expand Up @@ -95,20 +105,24 @@ def execute(self, expr, vals=None, commit=None):
# Get a new cursor (implicitly closing any previous cursor)
self.cursor = self.conn.cursor()

for subexpr in expr.split(';\n'):
for subexpr in expr.split(";\n"):
if vals is not None:
args = (subexpr, vals)
else:
args = (subexpr,)

if self.verbose:
print('Running:', args)
print("Running:", args)
self.cursor.execute(*args)

if (commit is None and self.autocommit) or commit:
self.commit()

def fetch(self, expr, vals=None,):
def fetch(
self,
expr,
vals=None,
):
"""
Return a generator that will fetch one row at a time after executing with args.
Expand All @@ -127,15 +141,22 @@ def fetch(self, expr, vals=None,):
while True:
vals = self.cursor.fetchone()
if vals:
yield dict(zip(cols, vals))
yield dict(zip(cols, vals, strict=False))
else:
if self.autocommit:
self.commit()
self.cursor.close()
break

def fetchone(self, expr, vals=None,):
"""Fetch one row after executing args. This always gets the first row of the
def fetchone(
self,
expr,
vals=None,
):
"""
Fetch one row.
Fetch one row after executing args. This always gets the first row of the
SQL query. Use ska_dbi.fetch() to get multiple rows one at a time.
Example usage::
Expand Down Expand Up @@ -179,11 +200,12 @@ def fetchall(self, expr, vals=None):

if self.numpy and vals:
import numpy

# Would be good to set dtype explicitly from database info instead of
# having numpy auto-determine types
return numpy.rec.fromrecords(vals, names=cols)
else:
return [dict(zip(cols, x)) for x in vals]
return [dict(zip(cols, x, strict=False)) for x in vals]

def insert(self, row, tablename, replace=False, commit=None):
"""Insert data row into table tablename.
Expand All @@ -210,13 +232,11 @@ def insert(self, row, tablename, replace=False, commit=None):

# Create the insert command depending on dbi. Start with the column
# value replacement strings
colrepls = ('?',) * len(cols)
colrepls = ("?",) * len(cols)

insert_str = "INSERT %s INTO %s (%s) VALUES (%s)"
replace_str = replace and 'OR REPLACE' or ''
cmd = insert_str % (replace_str, tablename,
','.join(cols),
','.join(colrepls))
replace_str = replace and "OR REPLACE" or ""
cmd = insert_str % (replace_str, tablename, ",".join(cols), ",".join(colrepls))

# Finally run the insert command
self.execute(cmd, vals, commit=commit)
Expand Down
7 changes: 4 additions & 3 deletions ska_dbi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

from .DBI import *

__version__ = ska_helpers.get_version('ska_dbi')
__version__ = ska_helpers.get_version("ska_dbi")


def test(*args, **kwargs):
'''
"""
Run py.test unit tests.
'''
"""
import testr

return testr.test(*args, **kwargs)
12 changes: 5 additions & 7 deletions ska_dbi/common.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
DEFAULT_CONFIG = {'sqlite': {'server': 'db.sql3'},
'sybase': {'server': 'sqlsao',
'user': 'aca_ops',
'database': 'axafapstat'}}
DEFAULT_CONFIG = {
"sqlite": {"server": "db.sql3"},
"sybase": {"server": "sqlsao", "user": "aca_ops", "database": "axafapstat"},
}


class NoPasswordError(Exception):
"""
Special Error for the case when password is neither supplied nor available
from a file.
Error when password is neither supplied nor available from a file.
"""
pass
Loading

0 comments on commit 37e1fa7

Please sign in to comment.