Skip to content

Commit f3e46ca

Browse files
authored
Merge pull request #104 from emreozcan/master
Add project pymetheus
2 parents 50d3dd7 + f3fed20 commit f3e46ca

33 files changed

+6026
-0
lines changed

Projects/pymetheus/LICENSE

Lines changed: 373 additions & 0 deletions
Large diffs are not rendered by default.

Projects/pymetheus/Pipfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[[source]]
2+
url = "https://pypi.org/simple"
3+
verify_ssl = true
4+
name = "pypi"
5+
6+
[packages]
7+
textual = "*"
8+
textual-dev = "*"
9+
10+
[dev-packages]
11+
12+
[requires]
13+
python_version = "3.11"

Projects/pymetheus/Pipfile.lock

Lines changed: 556 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
3+
from pymetheus.ui.app import PymetheusApp
4+
5+
app = PymetheusApp()
6+
7+
if __name__ == "__main__":
8+
app.run()
9+
sys.exit(app.return_code or 0)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from typing import TypeAlias
2+
3+
from .models_pymetheus import Item
4+
from .zotero_csl_interop import CslFieldName, get_field_type, FieldType, \
5+
zotero_item_type_to, FIELD_ZOTERO_CSL, CREATOR_ZOTERO_CSL
6+
7+
CslDateFieldValue: TypeAlias = list[list[int]]
8+
9+
10+
def split_date_field(field_value: str, /) -> CslDateFieldValue:
11+
"""Split a date field value into CSL-JSON format."""
12+
if "/" not in field_value:
13+
return [list(map(int, field_value.split("-")))]
14+
else:
15+
return [
16+
list(map(int, date_str.split("-")))
17+
for date_str in field_value.split("/")
18+
]
19+
20+
21+
def serialize_item(item: Item, /) -> dict:
22+
"""Serialize a pymetheus item to CSL-JSON."""
23+
24+
text_fields: dict[CslFieldName, str] = {}
25+
date_fields: dict[CslFieldName, dict[str, CslDateFieldValue]] = {}
26+
name_fields: dict[CslFieldName, list[dict[str, str]]] = {}
27+
28+
for zotero_field_name, field_value in item.field_data.items():
29+
field_type = get_field_type(zotero_field_name)
30+
csl_field_name = FIELD_ZOTERO_CSL[zotero_field_name]
31+
if field_type == FieldType.STANDARD:
32+
text_fields[csl_field_name] = field_value
33+
elif field_type == FieldType.DATE:
34+
date_fields[csl_field_name] = {
35+
"date-parts": split_date_field(field_value)
36+
}
37+
elif field_type == FieldType.NAME:
38+
raise ValueError(f"Unexpected name field: {csl_field_name}")
39+
else:
40+
raise ValueError(f"Field name with unknown type: {csl_field_name}")
41+
42+
for zotero_creator_type, name_data_list in item.creators.items():
43+
csl_field_name = CREATOR_ZOTERO_CSL[zotero_creator_type]
44+
name_fields[csl_field_name] = [
45+
name_data.as_dict() for name_data in name_data_list
46+
]
47+
48+
return {
49+
"type": zotero_item_type_to(item.type.name, "csl"),
50+
**text_fields,
51+
**date_fields,
52+
**name_fields,
53+
}

Projects/pymetheus/pymetheus/db.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import argparse
2+
import os
3+
import sqlite3
4+
from pathlib import Path
5+
6+
from .paths import (
7+
search_library_file_with_precedence,
8+
get_app_data_dir,
9+
get_default_library_path
10+
)
11+
12+
13+
def create_library_at(path: Path, /) -> sqlite3.Connection:
14+
path.parent.mkdir(exist_ok=True, parents=True)
15+
connection = sqlite3.connect(path)
16+
cursor = connection.cursor()
17+
18+
current_path = Path(__file__).resolve()
19+
ddl_path = current_path.parent / "ddl" / "main.sql"
20+
21+
cursor.executescript(ddl_path.read_text("utf-8"))
22+
connection.commit()
23+
return connection
24+
25+
26+
def open_library_at(path: Path, /) -> sqlite3.Connection:
27+
if path.exists():
28+
return sqlite3.connect(path)
29+
return create_library_at(path)
30+
31+
32+
def get_connection_from_args(
33+
parsed_args: argparse.Namespace,
34+
/
35+
) -> tuple[Path, sqlite3.Connection]:
36+
if not parsed_args.library:
37+
library_path = search_library_file_with_precedence(
38+
[
39+
Path(os.getcwd()),
40+
get_app_data_dir(),
41+
]
42+
)
43+
if not library_path:
44+
library_path = get_default_library_path()
45+
return library_path, create_library_at(library_path)
46+
else:
47+
return library_path, open_library_at(library_path)
48+
else:
49+
library_path: Path = parsed_args.library
50+
if library_path.exists():
51+
return library_path, open_library_at(library_path)
52+
else:
53+
return library_path, create_library_at(library_path)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
create table item
2+
(
3+
type text not null,
4+
field_data text not null,
5+
creators text not null
6+
);
7+
8+
create table collection
9+
(
10+
name text not null
11+
constraint collection_pkey
12+
primary key
13+
);
14+
15+
create table collection_entry
16+
(
17+
collection integer
18+
not null
19+
constraint collection_entry_collection_id_fkey
20+
references collection (rowid)
21+
on delete cascade,
22+
item integer
23+
not null
24+
constraint collection_entry_entry_id_fkey
25+
references item (rowid)
26+
on delete cascade
27+
);

0 commit comments

Comments
 (0)