Skip to content

Commit

Permalink
Update to python 3.9 (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
kmagusiak authored May 7, 2024
1 parent 2b80340 commit 9eaf8e8
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Odoo Connect",
"image": "mcr.microsoft.com/vscode/devcontainers/python:0-3.7",
"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye",

"customizations": {
"vscode": {
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/python-lint-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
Expand All @@ -23,11 +23,11 @@ jobs:
strategy:
matrix:
# lowest, common (default ubuntu LTS), newest
python-version: ["3.7", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
# don't use shallow checkout to determine an intermediary version correctly
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
Expand Down
6 changes: 3 additions & 3 deletions odoo_connect/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import urllib.parse
from typing import Dict, Optional
from typing import Optional

from .odoo_rpc import OdooClient, OdooModel, OdooServerError # noqa

Expand All @@ -20,7 +20,7 @@ def connect(
password: Optional[str] = None,
infer_parameters: bool = True,
check_connection: bool = True,
context: Optional[Dict] = None,
context: Optional[dict] = None,
monodb: bool = False,
**kw,
) -> OdooClient:
Expand Down Expand Up @@ -105,7 +105,7 @@ def connect(
return client
except (NotImplementedError, OdooConnectionError):
raise
except (ConnectionError, IOError, OdooServerError) as e:
except (ConnectionError, OSError, OdooServerError) as e:
raise OdooConnectionError(e)


Expand Down
14 changes: 7 additions & 7 deletions odoo_connect/attachment.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from typing import Dict, List, Optional, overload
from typing import Optional, overload

from .format import decode_binary
from .odoo_rpc import OdooClient, OdooModel, urljoin
Expand Down Expand Up @@ -47,7 +47,7 @@ def get_attachment(
if field_info.get("relation") == "ir.attachment":
if field_info.get("type") != "many2one":
raise RuntimeError(
"Field %s is not a many2one, here are the values: %s" % (field_name, value)
f"Field {field_name} is not a many2one, here are the values: {value}"
)
if not value:
return b''
Expand All @@ -59,7 +59,7 @@ def get_attachment(
return decode_binary(value)


def get_attachments(odoo: OdooClient, ids: List[int]) -> Dict[int, bytes]:
def get_attachments(odoo: OdooClient, ids: list[int]) -> dict[int, bytes]:
"""Get a list of tuples (name, raw_bytes) from ir.attachment by ids
:param odoo: Odoo client
Expand All @@ -71,8 +71,8 @@ def get_attachments(odoo: OdooClient, ids: List[int]) -> Dict[int, bytes]:


def list_attachments(
model: OdooModel, ids: List[int], *, domain=[], fields=[], generate_access_token=False
) -> List[Dict]:
model: OdooModel, ids: list[int], *, domain=[], fields=[], generate_access_token=False
) -> list[dict]:
"""List attachments
We search all attachments linked to the model and ids.
Expand Down Expand Up @@ -140,7 +140,7 @@ def attachment_url(d, _model_name=None, _id=None):


def _download_content(
odoo: OdooClient, url: str, *, params: Dict = {}, access_token: Optional[str] = None
odoo: OdooClient, url: str, *, params: dict = {}, access_token: Optional[str] = None
) -> bytes:
"""Download contents from a URL"""
log = logging.getLogger(__name__)
Expand Down Expand Up @@ -198,7 +198,7 @@ def download_image(
# REPORTS


def list_reports(model: OdooModel) -> List[Dict]:
def list_reports(model: OdooModel) -> list[dict]:
"""List of reports from a model"""
return model.odoo['ir.actions.report'].search_read(
[('model', '=', model.model)], ['name', 'report_type', 'report_name']
Expand Down
59 changes: 30 additions & 29 deletions odoo_connect/data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import json
import logging
from collections.abc import Iterable, Iterator
from dataclasses import dataclass
from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, cast
from typing import Any, Optional, cast

from .format import Formatter
from .odoo_rpc import OdooModel, urljoin
Expand All @@ -16,16 +17,16 @@


def make_batches(
data: Iterable[Dict], *, batch_size: int = 1000, group_by: str = ''
) -> Iterable[List[Dict]]:
data: Iterable[dict], *, batch_size: int = 1000, group_by: str = ''
) -> Iterable[list[dict]]:
"""Split an interable to a batched iterable
:param data: The iterable
:param batch_size: Target batch size (default: 1000)
:param group_by: field to group by (the value is kept in a single batch, can be empty)
:return: An iterable of batches
"""
batch: List[Dict] = []
batch: list[dict] = []
if group_by:
data = sorted(data, key=lambda d: d[group_by])
group_value = None
Expand Down Expand Up @@ -53,7 +54,7 @@ def load_data(
*,
method: str = "load",
method_row_type=None,
fields: Optional[List[str]] = None,
fields: Optional[list[str]] = None,
formatter: Optional[Formatter] = None,
):
"""Load the data into the model.
Expand Down Expand Up @@ -100,7 +101,7 @@ def load_data(

log.info("Load data using %s.%s(), %d records", model.model, method, len(data))
if method == 'load':
fields = [f.replace('.', '/') for f in cast(List[str], fields)]
fields = [f.replace('.', '/') for f in cast(list[str], fields)]
return model.execute(method, fields=fields, data=data)
if method == 'write':
return __load_data_write(model, data)
Expand All @@ -110,8 +111,8 @@ def load_data(


def __convert_to_type_list(
data: Iterable, fields: Optional[List[str]]
) -> Tuple[Iterable[List], List[str]]:
data: Iterable, fields: Optional[list[str]]
) -> tuple[Iterable[list], list[str]]:
idata = iter(data)
first_row = next(idata, None)
if first_row is None:
Expand All @@ -129,7 +130,7 @@ def __convert_to_type_list(
return data, fields


def __convert_to_type_dict(data: Iterable, fields: Optional[List[str]]) -> Iterable[Dict]:
def __convert_to_type_dict(data: Iterable, fields: Optional[list[str]]) -> Iterable[dict]:
idata = iter(data)
first_row = next(idata, None)
if first_row is None:
Expand All @@ -148,7 +149,7 @@ def __convert_to_type_dict(data: Iterable, fields: Optional[List[str]]) -> Itera
return data


def __load_data_write(model: OdooModel, data: List[Dict]) -> Dict:
def __load_data_write(model: OdooModel, data: list[dict]) -> dict:
"""Use multiple write() and create() calls to update data
:return: {'write_count': x, 'create_count': x, 'ids': [list of ids]}
Expand Down Expand Up @@ -192,19 +193,19 @@ def __str__(self) -> str:
class ExportData:
"""Exported data from Odoo"""

schema: List[Dict]
data: List[List]
schema: list[dict]
data: list[list]

@property
def column_names(self):
return [h['name'] for h in self.schema]

def to_dicts(self) -> Iterable[Dict]:
def to_dicts(self) -> Iterable[dict]:
"""Return the data as dicts"""
fields = self.column_names
return (dict(zip(fields, d)) for d in self.data)

def to_csv(self, with_header=True) -> Iterable[List[str]]:
def to_csv(self, with_header=True) -> Iterable[list[str]]:
"""Return the data for writing a csv file"""
if with_header:
yield self.column_names
Expand Down Expand Up @@ -244,7 +245,7 @@ def to_dbapi(self, con, table_name: str, *, only_data: bool = False, drop: bool
self.data,
)

def get_sql_columns(self) -> List[ColumnSpec]:
def get_sql_columns(self) -> list[ColumnSpec]:
"""Get the list of tuples (normalized_column_name, column_type) to write into a table"""
type_to_sql = {
'binary': 'binary',
Expand Down Expand Up @@ -275,7 +276,7 @@ def __str__(self) -> str:
return f"ExportData{self.column_names}({len(self.data)} rows)"


def fields_from_export(model: OdooModel, export_name: str) -> List[str]:
def fields_from_export(model: OdooModel, export_name: str) -> list[str]:
"""Return the list of fields in ir.exports"""
fields = model.odoo['ir.exports.line'].search_read(
[
Expand All @@ -290,7 +291,7 @@ def fields_from_export(model: OdooModel, export_name: str) -> List[str]:
return fields


def domain_from_filter(model: OdooModel, filter_name: str) -> Dict:
def domain_from_filter(model: OdooModel, filter_name: str) -> dict:
"""Return a tuple (domain, kwargs for search) from a filter name"""
filter_data = model.odoo['ir.filters'].search_read_dict(
[
Expand All @@ -311,8 +312,8 @@ def domain_from_filter(model: OdooModel, filter_name: str) -> Dict:

def export_data(
model: OdooModel,
domain: List,
fields: List[str],
domain: list,
fields: list[str],
*,
formatter: Optional[Formatter] = None,
expand_many: bool = False,
Expand Down Expand Up @@ -357,7 +358,7 @@ def export_data(


def add_fields(
model: OdooModel, data: List[Dict], by_field: str, fields: List[str] = ['id'], domain: List = []
model: OdooModel, data: list[dict], by_field: str, fields: list[str] = ['id'], domain: list = []
):
"""Add fields by querying the model
Expand All @@ -368,12 +369,12 @@ def add_fields(
:param domain: Additional domain to use
:raises Exception: When multiple results have the same by_field key
"""
domain_by_field: List[Any] = [(by_field, 'in', [d[by_field] for d in data])]
domain_by_field: list[Any] = [(by_field, 'in', [d[by_field] for d in data])]
domain = ['&'] + domain_by_field + (domain if domain else domain_by_field)
fetched_data = model.search_read_dict(domain, fields + [by_field])
index = {d.pop(by_field): d for d in fetched_data}
if len(index) != len(fetched_data):
raise Exception('%s is not unique in %s when adding fields' % (by_field, model.model))
raise Exception(f'{by_field} is not unique in {model.model} when adding fields')
for d in data:
updates = index.get(d[by_field])
if updates:
Expand All @@ -382,7 +383,7 @@ def add_fields(
d.update({f: None for f in fields})


def add_xml_id(model: OdooModel, data: List, *, id_name='id', xml_id_field='xml_id'):
def add_xml_id(model: OdooModel, data: list, *, id_name='id', xml_id_field='xml_id'):
"""Add a field containg the xml_id
:param model: The model
Expand Down Expand Up @@ -427,7 +428,7 @@ def add_xml_id(model: OdooModel, data: List, *, id_name='id', xml_id_field='xml_

def add_url(
model: OdooModel,
data: List,
data: list,
*,
url_field='url',
model_id_func=None,
Expand Down Expand Up @@ -463,7 +464,7 @@ def add_url(
raise TypeError('Cannot append the url to %s' % type(row))


def _flatten(value, access: List[str]) -> Any:
def _flatten(value, access: list[str]) -> Any:
if not access:
return value
if isinstance(value, dict):
Expand All @@ -473,7 +474,7 @@ def _flatten(value, access: List[str]) -> Any:
return False # default


def _expand_many(data: Iterable[Dict]) -> Iterator[Dict]:
def _expand_many(data: Iterable[dict]) -> Iterator[dict]:
for d in data:
should_yield = True
for k, v in d.items():
Expand All @@ -491,12 +492,12 @@ def _expand_many(data: Iterable[Dict]) -> Iterator[Dict]:


def flatten(
data: Iterable[Dict],
fields: List[str],
data: Iterable[dict],
fields: list[str],
*,
formatter: Optional[Formatter] = None,
expand_many: bool = False,
) -> Iterator[List]:
) -> Iterator[list]:
"""Flatten each dict with values into a single row"""
if expand_many:
data = _expand_many(data)
Expand Down
Loading

0 comments on commit 9eaf8e8

Please sign in to comment.