Skip to content

Commit

Permalink
Reorg project (#251)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd authored Jan 28, 2024
1 parent 83c5bb4 commit ec028fd
Show file tree
Hide file tree
Showing 17 changed files with 73 additions and 98 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ else()
message("Could not find clang-tidy installation - checks disabled")
endif()

add_subdirectory(pantab/src)
add_subdirectory(src/pantab)
15 changes: 14 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,22 @@ For an editable install of pantab you can simply run `pip install -ve .` from th
Tests are required for new changes and no code will be accepted without them. You should first set up your test in the appropriate module in the `pantab/tests` directory. You can then run the test suite with

```sh
pytest pantab
pytest tests
```

For more advanced use cases where you may want to debug compiled extensions, you _may_ need to build the extension in the source tree and invoke pytest from the src folder. As an example:

```sh
cmake -S . -B . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build .
cd src
python -m pytest ../tests
```

Will work as well. You may want to run ``git clean -xfd`` when done with the debugging to clean up the source tree.

pantab would love contributions to make this work *out of source* if it is possible!

### Style guidelines for code changes

Note that `pantab` uses `black`, `flake8` and `isort` to manage code style. Simply run pre-commit. If pre-commit modifies files, simply add them and run pre-commit again. Note, if you've already run `pre-commit install` it will automatically run before every commit regardless.
Expand Down
10 changes: 0 additions & 10 deletions pantab/_tester.py

This file was deleted.

Empty file removed pantab/src/__init__.py
Empty file.
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ dev = ["pytest"]
filename = "NEWS.rst"

[tool.pytest.ini_options]
testpaths = [
"pantab/tests",
testpaths = ["tests"]
addopts = [
"--import-mode=importlib",
]

[tool.mypy]
Expand All @@ -67,7 +68,7 @@ known_first_party = "pantab"
build = "cp39-*64 cp310-*64 cp311-*64 cp312-*64"
skip = "*musllinux*"

test-command = "pytest --import-mode=importlib {project}/pantab/tests"
test-command = "pytest {project}/tests"
test-requires = ["pytest", "pandas>=2.0.0", "polars", "numpy"]

[tool.ruff]
Expand Down
16 changes: 8 additions & 8 deletions pantab/src/CMakeLists.txt → src/pantab/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
nanobind_add_module(pantab NOMINSIZE pantab.cpp numpy_datetime.cpp)
target_include_directories(pantab PUBLIC ${Python_NumPy_INCLUDE_DIRS})
target_link_libraries(pantab
nanobind_add_module(libpantab NOMINSIZE libpantab.cpp numpy_datetime.cpp)
target_include_directories(libpantab PUBLIC ${Python_NumPy_INCLUDE_DIRS})
target_link_libraries(libpantab
PRIVATE Tableau::tableauhyperapi-cxx
PRIVATE nanoarrow
)
set_target_properties(pantab PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
set_target_properties(libpantab PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
set_target_properties(nanoarrow
PROPERTIES POSITION_INDEPENDENT_CODE
ON)

install(TARGETS pantab
LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME}/src)
install(TARGETS libpantab
LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME}/)

if(WIN32)
set(HYPERAPI_LIB_NAME "tableauhyperapi.lib")
Expand All @@ -26,6 +26,6 @@ endif()
# Auditwheel doesn't know how to handle the cmake dependencies
# so we manually install here and exclude from auditwheel
install(FILES ${tableauhyperapi-cxx_SOURCE_DIR}/lib/${HYPERAPI_LIB_NAME}
DESTINATION ${SKBUILD_PROJECT_NAME}/src)
DESTINATION ${SKBUILD_PROJECT_NAME}/)
install(DIRECTORY "${tableauhyperapi-cxx_SOURCE_DIR}/${HYPERAPI_BIN_LOC}/"
DESTINATION ${SKBUILD_PROJECT_NAME}/src/hyper)
DESTINATION ${SKBUILD_PROJECT_NAME}/hyper)
6 changes: 2 additions & 4 deletions pantab/__init__.py → src/pantab/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
__version__ = "4.0.0rc"


from ._reader import frame_from_hyper, frame_from_hyper_query, frames_from_hyper
from ._tester import test
from ._writer import frame_to_hyper, frames_to_hyper
from pantab._reader import frame_from_hyper, frame_from_hyper_query, frames_from_hyper
from pantab._writer import frame_to_hyper, frames_to_hyper

__all__ = [
"__version__",
Expand All @@ -12,5 +11,4 @@
"frames_from_hyper",
"frame_to_hyper",
"frames_to_hyper",
"test",
]
2 changes: 1 addition & 1 deletion pantab/_reader.py → src/pantab/_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tableauhyperapi as tab_api

import pantab._types as pantab_types
import pantab.src.pantab as libpantab # type: ignore
import pantab.libpantab as libpantab # type: ignore


def frame_from_hyper_query(
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion pantab/_writer.py → src/pantab/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tableauhyperapi as tab_api

import pantab._types as pantab_types
import pantab.src.pantab as libpantab # type: ignore
import pantab.libpantab as libpantab # type: ignore


def _validate_table_mode(table_mode: Literal["a", "w"]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pantab/src/pantab.cpp → src/pantab/libpantab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ auto read_from_hyper_query(const std::string &path, const std::string &query)
return result;
}

NB_MODULE(pantab, m) { // NOLINT
NB_MODULE(libpantab, m) { // NOLINT
m.def("write_to_hyper", &write_to_hyper, nb::arg("dict_of_capsules"),
nb::arg("path"), nb::arg("table_mode"), nb::arg("json_columns"),
nb::arg("geo_columns"))
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 8 additions & 8 deletions pantab/tests/test_reader.py → tests/test_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
import pandas.testing as tm
import tableauhyperapi as tab_api

import pantab as pt
import pantab


def test_read_doesnt_modify_existing_file(frame, tmp_hyper):
pt.frame_to_hyper(frame, tmp_hyper, table="test")
pantab.frame_to_hyper(frame, tmp_hyper, table="test")
last_modified = tmp_hyper.stat().st_mtime

# Try out our read methods
pt.frame_from_hyper(tmp_hyper, table="test")
pt.frames_from_hyper(tmp_hyper)
pantab.frame_from_hyper(tmp_hyper, table="test")
pantab.frames_from_hyper(tmp_hyper)

# Neither should not update file stats
assert last_modified == tmp_hyper.stat().st_mtime
Expand Down Expand Up @@ -46,16 +46,16 @@ def test_reads_nullable_columns(tmp_hyper, compat):
inserter.add_rows([[1], [2]])
inserter.execute()

result = pt.frame_from_hyper(tmp_hyper, table=table_name)
result = pantab.frame_from_hyper(tmp_hyper, table=table_name)
expected = pd.DataFrame([[1], [2]], dtype="int32[pyarrow]", columns=[column_name])
compat.assert_frame_equal(result, expected)


def test_read_query(frame, tmp_hyper):
pt.frame_to_hyper(frame, tmp_hyper, table="test")
pantab.frame_to_hyper(frame, tmp_hyper, table="test")

query = "SELECT int16 AS i, '_' || int32 AS _i2 FROM test"
result = pt.frame_from_hyper_query(tmp_hyper, query)
result = pantab.frame_from_hyper_query(tmp_hyper, query)

expected = pd.DataFrame([[1, "_2"], [6, "_7"], [0, "_0"]], columns=["i", "_i2"])
expected = expected.astype({"i": "int16[pyarrow]", "_i2": "large_string[pyarrow]"})
Expand Down Expand Up @@ -95,5 +95,5 @@ def test_read_varchar(tmp_hyper):
[["foo"], ["bar"]], columns=[column_name], dtype="large_string[pyarrow]"
)

result = pt.frame_from_hyper(tmp_hyper, table=table_name)
result = pantab.frame_from_hyper(tmp_hyper, table=table_name)
tm.assert_frame_equal(result, expected)
24 changes: 14 additions & 10 deletions pantab/tests/test_roundtrip.py → tests/test_roundtrip.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pyarrow as pa
from tableauhyperapi import TableName

import pantab as pt
import pantab


def test_basic(frame, roundtripped, tmp_hyper, table_name, table_mode, compat):
Expand All @@ -11,15 +11,15 @@ def test_basic(frame, roundtripped, tmp_hyper, table_name, table_mode, compat):
expected = compat.drop_columns(expected, ["interval"])

# Write twice; depending on mode this should either overwrite or duplicate entries
pt.frame_to_hyper(
pantab.frame_to_hyper(
frame,
tmp_hyper,
table=table_name,
table_mode=table_mode,
json_columns={"json"},
geo_columns={"geography"},
)
pt.frame_to_hyper(
pantab.frame_to_hyper(
frame,
tmp_hyper,
table=table_name,
Expand All @@ -28,7 +28,9 @@ def test_basic(frame, roundtripped, tmp_hyper, table_name, table_mode, compat):
geo_columns={"geography"},
)

result = pt.frame_from_hyper(tmp_hyper, table=table_name, return_type=return_type)
result = pantab.frame_from_hyper(
tmp_hyper, table=table_name, return_type=return_type
)

if table_mode == "a":
expected = compat.concat_frames(expected, expected)
Expand All @@ -45,22 +47,22 @@ def test_multiple_tables(
expected = compat.drop_columns(expected, ["interval"])

# Write twice; depending on mode this should either overwrite or duplicate entries
pt.frames_to_hyper(
pantab.frames_to_hyper(
{table_name: frame, "table2": frame},
tmp_hyper,
table_mode=table_mode,
json_columns={"json"},
geo_columns={"geography"},
)
pt.frames_to_hyper(
pantab.frames_to_hyper(
{table_name: frame, "table2": frame},
tmp_hyper,
table_mode=table_mode,
json_columns={"json"},
geo_columns={"geography"},
)

result = pt.frames_from_hyper(tmp_hyper, return_type=return_type)
result = pantab.frames_from_hyper(tmp_hyper, return_type=return_type)

if table_mode == "a":
expected = compat.concat_frames(expected, expected)
Expand All @@ -85,15 +87,15 @@ def test_empty_roundtrip(
# object case is by definition vague, so lets punt that for now
frame = compat.drop_columns(frame, ["object"])
empty = compat.empty_like(frame)
pt.frame_to_hyper(
pantab.frame_to_hyper(
empty,
tmp_hyper,
table=table_name,
table_mode=table_mode,
json_columns={"json"},
geo_columns={"geography"},
)
pt.frame_to_hyper(
pantab.frame_to_hyper(
empty,
tmp_hyper,
table=table_name,
Expand All @@ -102,7 +104,9 @@ def test_empty_roundtrip(
geo_columns={"geography"},
)

result = pt.frame_from_hyper(tmp_hyper, table=table_name, return_type=return_type)
result = pantab.frame_from_hyper(
tmp_hyper, table=table_name, return_type=return_type
)

expected = compat.drop_columns(expected, ["object"])
expected = compat.empty_like(expected)
Expand Down
Loading

0 comments on commit ec028fd

Please sign in to comment.