Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lint #15

Merged
merged 45 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
78730df
Rewrite TestBasicRange1DAnnotator to pytest
hoxbro Jun 29, 2023
37e8ab2
Rewrite TestBasicRange2DAnnotator to pytest
hoxbro Jun 29, 2023
309b6e4
Convert test_table_region_df to pytest
hoxbro Jun 30, 2023
0fc2624
Run ruff --select=pt
hoxbro Jun 30, 2023
8f5bbd9
Update TestBasicPoint1DAnnotator
hoxbro Jun 30, 2023
4c40e2b
Update TestBasicPoint2DAnnotator
hoxbro Jun 30, 2023
c707e32
Split up into basic and advanced
hoxbro Jun 30, 2023
ee08b18
Rewrite test_connectors
hoxbro Jun 30, 2023
266ce67
Remove commented out code
hoxbro Jun 30, 2023
e2347b9
Update test_annotator_advanced
hoxbro Jun 30, 2023
674b4ba
Update test to give all output
hoxbro Jun 30, 2023
7bd831c
update database fields
hoxbro Jun 30, 2023
1fa0813
Refactor pytest fixtures
hoxbro Jun 30, 2023
23fef76
DRY fixtures
hoxbro Jun 30, 2023
cfe5e01
Clean up test_connectors
hoxbro Jun 30, 2023
42c25e1
Remove database in tests
hoxbro Jun 30, 2023
d2d8a66
Duplicate behavior
hoxbro Jun 30, 2023
bd4bf38
Support all database for test_add_three_rows_delete_one
hoxbro Jul 4, 2023
1d49c19
Merge branch 'use_pytest' into fix_duplicate
hoxbro Jul 4, 2023
cf55cb4
Remove duplicate code in test and remove list in init
hoxbro Jul 5, 2023
6bd72c0
Move loading of annotation_table into its class
hoxbro Jul 5, 2023
c4d48bb
Add init
hoxbro Jul 5, 2023
37ae038
Remove mutable input
hoxbro Jul 5, 2023
7c2c6ca
Add return_commits
hoxbro Jul 5, 2023
236baa2
Fix multiple_region_annotator test
hoxbro Jul 5, 2023
f714169
Fix test_multiplot_add_annotation and remove annotation_tables from c…
hoxbro Jul 5, 2023
4a38c19
Don't initialize connector
hoxbro Jul 5, 2023
c02b412
Combine test_reconnect
hoxbro Jul 5, 2023
79a8efe
Remove all drop_duplicates
hoxbro Jul 5, 2023
fddae93
Clean up
hoxbro Jul 10, 2023
c729118
Merge branch 'main' into fix_duplicate
hoxbro Aug 9, 2023
36fd101
Add ruff + pre-commit
hoxbro Aug 9, 2023
78596b5
Add clean_notebook and codespell
hoxbro Aug 9, 2023
c05465f
Add generic pre-commit hooks
hoxbro Aug 9, 2023
86b7723
Update pre-commit
hoxbro Aug 9, 2023
117d167
Add Bugbear to Ruff
hoxbro Aug 9, 2023
e6f7db9
Add isort to Ruff
hoxbro Aug 9, 2023
c425917
Enable RUF005
hoxbro Aug 9, 2023
8859183
Run lint
hoxbro Aug 9, 2023
6e1b64f
Fix import
hoxbro Aug 9, 2023
06104e1
Add pre-commit to CI and add fmt to hatch
hoxbro Aug 9, 2023
257d0cf
Update pre-commit
hoxbro Aug 18, 2023
7c5227b
Fix empty mask bug
hoxbro Aug 18, 2023
4dd9dd2
Merge branch 'fix_duplicate' into add_lint
hoxbro Aug 28, 2023
7ac758d
Merge branch 'main' into add_lint
hoxbro Aug 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ concurrency:
cancel-in-progress: true

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pre-commit/[email protected]
unit_test_suite:
name: Unit tests on ${{ matrix.os }} with Python ${{ matrix.python-version }}
needs: [pre-commit]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ __pycache__/
.ipynb_checkpoints/
.pytest_cache
dist
scratch/
scratch/
33 changes: 33 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This is the configuration for pre-commit, a local framework for managing pre-commit hooks
# Check out the docs at: https://pre-commit.com/

exclude: (\.min\.js$|\.svg$|\.html$)
default_stages: [commit]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-builtin-literals
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-toml
- id: detect-private-key
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.285
hooks:
- id: ruff
args: [holonote]
files: holonote/
- repo: https://github.com/hoxbro/clean_notebook
rev: v0.1.10
hooks:
- id: clean-notebook
- repo: https://github.com/codespell-project/codespell
rev: v2.2.5
hooks:
- id: codespell
additional_dependencies:
- tomli
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ have different types:
data, containing information that is not to be visualized by
`holonote`. These are defined by the user or application and can have
arbitrary types and contents. A complete set of fields together with one
or more regions constitutes an annotation.
or more regions constitutes an annotation.
23 changes: 5 additions & 18 deletions examples/Basics.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"id": "616fd061-fffd-4f1a-94ce-dc8bc6b9d5bd",
"metadata": {},
"source": [
"**Note**: The tools made available by the region editor are appropriate to both the enable region types as well as the dimensionality of the elemnt (here, a single key dimension along the x-axis)\n"
"**Note**: The tools made available by the region editor are appropriate to both the enable region types as well as the dimensionality of the element (here, a single key dimension along the x-axis)\n"
]
},
{
Expand Down Expand Up @@ -141,7 +141,7 @@
"id": "c0fd9b3f-8827-4e02-bb03-8edfbde88eb1",
"metadata": {},
"source": [
"You can set the range of interest programatically as well:"
"You can set the range of interest programmatically as well:"
]
},
{
Expand Down Expand Up @@ -227,7 +227,7 @@
"id": "18335801-7230-40b9-a5b1-ed4d7050deec",
"metadata": {},
"source": [
"Note that uuid values are randomly generated (by default) which means we do not know what these values will be ahead of time. As a result we need a programatic way to access them. Using the dataframe index directly is awkard, so annotators offer a more natural, interactive way to select annotations - simply click on them in the plot to select them.\n",
"Note that uuid values are randomly generated (by default) which means we do not know what these values will be ahead of time. As a result we need a programmatic way to access them. Using the dataframe index directly is awkward, so annotators offer a more natural, interactive way to select annotations - simply click on them in the plot to select them.\n",
"\n",
"Click on a range region in the plot above and run the following cell to see it's uuid:"
]
Expand Down Expand Up @@ -702,7 +702,7 @@
"\n",
"### Styling the annotator\n",
"\n",
"You can set the style either throught the `_style` keywords in `.overlay`:"
"You can set the style either through the `_style` keywords in `.overlay`:"
]
},
{
Expand Down Expand Up @@ -737,22 +737,9 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
Expand Down
21 changes: 4 additions & 17 deletions examples/Basics_2D.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"id": "c0fd9b3f-8827-4e02-bb03-8edfbde88eb1",
"metadata": {},
"source": [
"You can set the range of interest programatically as well:"
"You can set the range of interest programmatically as well:"
]
},
{
Expand Down Expand Up @@ -220,7 +220,7 @@
"id": "18335801-7230-40b9-a5b1-ed4d7050deec",
"metadata": {},
"source": [
"Note that uuid values are randomly generated (by default) which means we do not know what these values will be ahead of time. As a result we need a programatic way to access them. Using the dataframe index directly is awkard, so annotators offer a more natural, interactive way to select annotations - simply click on them in the plot to select them.\n",
"Note that uuid values are randomly generated (by default) which means we do not know what these values will be ahead of time. As a result we need a programmatic way to access them. Using the dataframe index directly is awkward, so annotators offer a more natural, interactive way to select annotations - simply click on them in the plot to select them.\n",
"\n",
"Click on a range region in the plot above and run the following cell to see it's uuid:"
]
Expand Down Expand Up @@ -678,7 +678,7 @@
"\n",
"### Styling the annotator\n",
"\n",
"You can set the style either throught the `_style` keywords in `.overlay`:"
"You can set the style either through the `_style` keywords in `.overlay`:"
]
},
{
Expand Down Expand Up @@ -713,22 +713,9 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
Expand Down
5 changes: 3 additions & 2 deletions holonote/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import annotate
from . import editor
from __future__ import annotations

from . import annotate, editor # noqa: F401
12 changes: 10 additions & 2 deletions holonote/annotate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
from .annotator import Annotator
from .connector import Connector, SQLiteDB, AutoIncrementKey, UUIDHexStringKey, UUIDBinaryKey
from __future__ import annotations

from .annotator import Annotator # noqa: F401
from .connector import ( # noqa: F401
AutoIncrementKey,
Connector,
SQLiteDB,
UUIDBinaryKey,
UUIDHexStringKey,
)
from .table import *
18 changes: 9 additions & 9 deletions holonote/annotate/annotator.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import sys
import weakref
from __future__ import annotations

import holoviews as hv
import numpy as np
import pandas as pd
import param
from bokeh.models.tools import BoxSelectTool, HoverTool
from holoviews.element.selection import Selection1DExpr
from .connector import Connector, SQLiteDB, AnnotationTable

from .connector import Connector, SQLiteDB
from .table import AnnotationTable


class Indicator:
Expand All @@ -17,11 +18,11 @@ class Indicator:
"""

range_style = dict(color='red', alpha=0.4, apply_ranges=False)
point_style = dict()
point_style = {}
indicator_highlight = {'alpha':(0.7,0.2)}

edit_range_style = dict(alpha=0.4, line_alpha=1, line_width=1, line_color='black')
edit_point_style = dict()
edit_point_style = {}

@classmethod
def indicator_style(cls, range_style, point_style, highlighters):
Expand Down Expand Up @@ -167,13 +168,12 @@ def df(self):
region_column_names.extend(point_column_names)
view = pd.concat(views)
view = view.rename(columns={'_id':field_name})
column_ordering = [field_name] + region_column_names + fields_columns
column_ordering = [field_name, *region_column_names, *fields_columns]
return view[column_ordering].set_index(field_name)


def refresh(self, clear=False):
"Method to update display state of the annotator and optionally clear stale visual state"
pass

def set_annotation_table(self, annotation_table): # FIXME! Won't work anymore, set_connector??
self._region = {}
Expand Down Expand Up @@ -430,7 +430,7 @@ def clear_indicated_region(self):
def selection_element(self):
if self.element is None:
kdims = list(self.kdim_dtypes.keys())
kdim_dtype = list(self.kdim_dtypes.values())[0]
kdim_dtype = next(iter(self.kdim_dtypes.values()))
return hv.Curve(([kdim_dtype(), kdim_dtype()],
[0,1]), kdims=kdims) # Note: Any concrete Selection1dExpr will do...

Expand Down Expand Up @@ -596,7 +596,7 @@ def _build_hover_tool(self):
extra_cols = [(col, '@{%s}' % col.replace(' ','_')) for col in self.annotation_table._field_df.columns]
region_tooltips = []
region_formatters = {}
for direction, kdim, dtype in zip(['x','y'], self.kdim_dtypes.keys(), self.kdim_dtypes.values()):
for direction, kdim in zip(['x','y'], self.kdim_dtypes.keys()):
if self.kdim_dtypes[kdim] is np.datetime64:
region_tooltips.append((f'start {kdim}', f'@{direction}0{{%F}}'))
region_tooltips.append((f'end {kdim}', f'@{direction}1{{%F}}'))
Expand Down
32 changes: 15 additions & 17 deletions holonote/annotate/connector.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import os
import uuid
import sqlite3
from __future__ import annotations

import datetime as dt
import sqlite3
import uuid

import param
import pandas as pd
import numpy as np
import pandas as pd
import param

try:
import sqlalchemy
except:
except ModuleNotFoundError:
sqlalchemy = None

from .table import AnnotationTable


class PrimaryKey(param.Parameterized):
"""
Generator of the primary key used to keep track of annotations in
HoloViews.

The generated key is used to reference annotations until they are
comitted, at which point they may 1) be inserted in the database as
committed, at which point they may 1) be inserted in the database as
the primary key value (policy='insert') 2) are checked against the
primary key value chosen by the database which is expected to match
in most cases.

In real situations where the key is chosen by the databse, the key
In real situations where the key is chosen by the database, the key
generated will *not* always match the actual key assigned. The
policy parameter decides the resulting behavior in these cases.
"""
Expand All @@ -44,7 +43,7 @@ class PrimaryKey(param.Parameterized):
def __call__(self, connector, key_list=None):
"""
The key list is the current list of index values that are
outstanding (i.e. have not been comitted).
outstanding (i.e. have not been committed).
"""
raise NotImplementedError

Expand Down Expand Up @@ -133,7 +132,6 @@ class WidgetKey(PrimaryKey):
Placeholder for a concept where the user can insert a primary key
value via a widget.
"""
pass



Expand Down Expand Up @@ -186,7 +184,7 @@ def field_value_to_type(cls, value):
elif isinstance(value, param.Parameter) and value.default is not None:
return type(value.default)
else:
raise Exception(f'Connector cannot handle type {str(type(value))}')
raise Exception(f'Connector cannot handle type {type(value)!s}')

@classmethod
def schema_from_field_values(cls, fields):
Expand Down Expand Up @@ -231,7 +229,7 @@ def _incompatible_schema_check(self, expected_keys, columns, fields, region_type
missing_region_columns = set(expected_keys) - non_field_columns
if missing_region_columns:
raise Exception(msg_prefix
+ f'Missing {repr(region_type)} region columns {missing_region_columns}. '
+ f'Missing {region_type!r} region columns {missing_region_columns}. '
+ msg_suffix)


Expand Down Expand Up @@ -315,7 +313,7 @@ def get_tables(self):

def create_table(self, column_schema=None):
column_schema = column_schema if column_schema else self.column_schema
column_spec = ',\n'.join(['{name} {spec}'.format(name=name, spec=spec)
column_spec = ',\n'.join([f'{name} {spec}'
for name, spec in column_schema.items()])
create_table_sql = f'CREATE TABLE IF NOT EXISTS {self.table_name} (' + column_spec + ');'
self.cursor.execute(create_table_sql)
Expand All @@ -340,7 +338,7 @@ def add_row(self, **fields):
columns = columns[1:]

placeholders = ', '.join(['?'] * len(field_values))
self.cursor.execute(f"INSERT INTO {self.table_name} {str(columns)} VALUES({placeholders});", field_values)
self.cursor.execute(f"INSERT INTO {self.table_name} {columns!s} VALUES({placeholders});", field_values)
self.primary_key.validate(self.cursor.lastrowid, fields[self.primary_key.field_name])
self.con.commit()

Expand All @@ -359,7 +357,7 @@ def update_row(self, **updates): # updates as a dictionary OR remove posarg?
id_val = updates.pop(self.primary_key.field_name)
set_updates = ', '.join('\"' + k + '\"' + " = ?" for k in updates.keys())
query = f"UPDATE {self.table_name} SET " + set_updates + f" WHERE \"{self.primary_key.field_name}\" = ?;"
self.cursor.execute(query, list(updates.values()) + [id_val])
self.cursor.execute(query, [*updates.values(), id_val])
self.con.commit()

def add_schema(self, schema):
Expand Down
Loading