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 exact date query to enable logyesterday #96

Merged
merged 10 commits into from
May 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:

jobs:
publish:
if: github.repository == 'thingsapi/things.py'
runs-on: ubuntu-latest
environment: github-pages
steps:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
make deps-install
- name: Run docs
run: |
pip install pytest
pip install pdoc
make doc
- name: Commit files
Expand All @@ -29,6 +30,7 @@ jobs:
git config --local user.name "github-actions[bot]"
git commit -m "Updated docs" -a||true
- name: Push changes
if: github.repository == 'thingsapi/things.py'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ jobs:
pip install coverage pytest
make test testdoc
- name: "Upload coverage to Codecov"
uses: codecov/codecov-action@v1
if: github.repository == 'thingsapi/things.py'
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
- name: Run lint
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ testdoc: ## Test the code within the documentation

.PHONY: doc
doc: install ## Document the code
@type pytest >/dev/null 2>&1 || (echo "Run '$(PIP) install pytest' first." >&2 ; exit 1)
@#$(PYDOC) $(SRC_CORE).api
@$(PDOC) -o $(DST_DOCS) -d numpy -n $(SRC_CORE)
@echo "Now open $(DST_DOCS)"
Expand Down Expand Up @@ -100,7 +101,8 @@ lint: code-style code-lint ## Lint everything

deps-install: ## Install the dependencies
@type $(PIPENV) >/dev/null 2>&1 || (echo "Run e.g. 'brew install pipenv' first." >&2 ; exit 1)
@$(PIPENV) install
@$(PIPENV) install --dev
npm install pyright

feedback: ## Give feedback
@open https://github.com/thingsapi/things.py/issues
Expand Down Expand Up @@ -131,3 +133,6 @@ db-to-things:

db-from-things:
@cp ~/Library/Group\ Containers/JLMPQHK86H.com.culturedcode.ThingsMac/Things\ Database.thingsdatabase/main.sqlite* tests/

info:
pipenv --venv
12 changes: 12 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,17 @@ name = "pypi"

[dev-packages]

black = "*"
coverage = "*"
flake8 = "*"
mypy = "*"
pycodestyle = "*"
pydocstyle = "*"
pylama = "*"
pylint = "*"
pyright = "*"
pytest = "*"
vulture = "*"

[requires]
python_version = "3"
456 changes: 454 additions & 2 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions tests/test_things.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def test_logbook(self):
self.assertEqual(0, len(tasks))
tasks = things.logbook(stop_date="2021-03-28")
self.assertEqual(21, len(tasks))
tasks = things.logbook(stop_date="2021-03-27", exact=True)
self.assertEqual(0, len(tasks))

def test_canceled(self):
tasks = things.canceled()
Expand Down
2 changes: 1 addition & 1 deletion things/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
__copyright__ = "2021 Alexander Willner & Michael Belfrage"
__credits__ = ["Alexander Willner", "Michael Belfrage"]
__license__ = "Apache License 2.0"
__version__ = "0.0.14"
__version__ = "0.0.15"
__maintainer__ = ["Alexander Willner", "Michael Belfrage"]
__email__ = "[email protected]"
__status__ = "Development"
Expand Down
6 changes: 6 additions & 0 deletions things/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ def tasks(uuid=None, include_items=False, **kwargs): # noqa: C901
Note: this includes today's date.
- `start_date == None` (default), then include all tasks.

stop_date : as start_date, signifies the date of completion

exact : bool, optional
- `exact == False` (default) compare date provided with >=
- `exact == True`, compare date with ==

deadline : bool, str or None, optional
- `deadline == False`, only include tasks _without_ a deadline.
- `deadline == True`, only include tasks _with_ a deadline.
Expand Down
26 changes: 18 additions & 8 deletions things/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def get_tasks( # pylint: disable=R0914
tag=None,
start_date=None,
stop_date=None,
exact=False,
deadline=None,
deadline_suppressed=None,
trashed=False,
Expand Down Expand Up @@ -224,10 +225,10 @@ def get_tasks( # pylint: disable=R0914
# TK: might consider executing SQL with parameters instead.
# See: https://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.execute

start_filter: str = START_TO_FILTER.get(str(start), "")
status_filter: str = STATUS_TO_FILTER.get(str(status), "")
trashed_filter: str = TRASHED_TO_FILTER.get(trashed, "")
type_filter: str = TYPE_TO_FILTER.get(str(type), "")
start_filter: str = START_TO_FILTER.get(start, "") if start else ""
status_filter: str = STATUS_TO_FILTER.get(status, "") if status else ""
trashed_filter: str = get_allow_none(TRASHED_TO_FILTER, trashed, "")
type_filter: str = TYPE_TO_FILTER.get(type, "") if type else ""

# Sometimes a task is _not_ set to trashed, but its context
# (project or heading it is contained within) is set to trashed.
Expand All @@ -253,7 +254,7 @@ def get_tasks( # pylint: disable=R0914
{make_filter("TASK.deadlineSuppressionDate", deadline_suppressed)}
{make_filter("TAG.title", tag)}
{make_date_filter(f"TASK.{DATE_START}", start_date)}
{make_date_filter(f"TASK.{DATE_STOP}", stop_date)}
{make_date_filter(f"TASK.{DATE_STOP}", stop_date, exact)}
{make_date_filter(f"TASK.{DATE_DEADLINE}", deadline)}
{make_date_range_filter(f"TASK.{DATE_CREATED}", last)}
{make_search_filter(search_query)}
Expand Down Expand Up @@ -474,6 +475,12 @@ def execute_query(self, sql_query, parameters=(), row_factory=None):

# Helper functions

def get_allow_none(dictionary, key, default):
"""Get key with default from dict, allows none to be passed as key."""
if key is None:
return default
return dictionary.get(key, default)


def make_tasks_sql_query(where_predicate=None, order_predicate=None):
"""Make SQL query for Task table."""
Expand Down Expand Up @@ -636,7 +643,7 @@ def make_filter(column, value):
}.get(value, default)


def make_date_filter(date_column: str, value) -> str:
def make_date_filter(date_column: str, value, exact=False) -> str:
"""
Return a SQL filter for date columns.

Expand All @@ -651,6 +658,9 @@ def make_date_filter(date_column: str, value) -> str:
ISO 8601 date str is in the format "YYYY-MM-DD".
`None` indicates any value.

exact : bool
matches for exact date of date_column

Returns
-------
str
Expand Down Expand Up @@ -685,7 +695,7 @@ def make_date_filter(date_column: str, value) -> str:
# Check for ISO 8601 date str
datetime.date.fromisoformat(value)
threshold = f"date('{value}')"
comparator = ">="
comparator = '==' if exact else '>='
except ValueError:
# "future" or "past"
validate("value", value, ["future", "past"])
Expand Down Expand Up @@ -778,7 +788,7 @@ def make_truthy_filter(column: str, value) -> str:
return f"AND NOT IFNULL({column}, 0)"


def make_search_filter(query: str) -> str:
def make_search_filter(query) -> str:
"""
Return a SQL filter to search tasks by a string query.

Expand Down