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

Update scalar implementation #162

Merged
merged 13 commits into from
Oct 24, 2021
33 changes: 33 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/bugs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: Bug fix
about: Create a pull request to fix a bug
title: ""
labels: bug
assignees: ""
---

<!--- Provide a general summary of your changes in the Title above -->

## Description

<!--- Describe your changes in detail -->

## Related Issue

<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

## How Has This Been Tested?

<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

## Screenshots (if appropriate):
46 changes: 46 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/large_change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
name: Significant Change
about: Create a pull request to make a significant change
title: ""
assignees: ""
---

# Pull Request Template

## Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the unit tests that you added to verify your changes. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

**Test Configuration**:

Please decribe any test configuration changes.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
- [ ] I have checked my code and corrected any misspellings
24 changes: 24 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/small_change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: Minor Change
about: Create a pull request to make a minor change
title: ""
assignees: ""
---

- **Please check if the PR fulfills these requirements**

* [ ] The package maintains 100% code coverage.
* [ ] Tests for the changes have been added (for bug fixes / features)
* [ ] Docs have been added / updated (for bug fixes / features)

- **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)

- **What is the current behavior?** (You can also link to an open issue here)

- **What is the new behavior (if this is a feature change)?**

- **Does this PR introduce a breaking change?** (What changes might users need to make in their application due to this PR?)

- **Issue** (Link to the relevant open issue.)

- **Other information**:
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
project = "mock-alchemy"
author = "Rajiv Sarvepalli"
copyright = f"{datetime.now().year}, {author}"
version = "0.2.4"
version = "0.2.5"
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
Expand Down
49 changes: 33 additions & 16 deletions docs/user_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ session is unable to actually apply any filters so it returns everything::
Scalar in Sessions
++++++++++++++++++
You can now mock `scalar() <https://docs.sqlalchemy.org/en/14/orm/query.html#sqlalchemy.orm.Query.scalar>`__.
The below example shows querying on a specific attribute and returning it using ``scalar()``.
To do this you must create another object to represent the returned attribute (in this case, it is called
``Attribute``). Scalar is then used to get the first column of the first row as shown.
There are several limitations with using scalar. One is that when querying on column(s), your mocked data object
must return an indexable sequence. However, when querying on a table, the returned object must not be indexable.
This is due to the property of `scalar()` in native SQLAlchemy returning an object when a select is performed on a table and
returning a specific column value when a select is performed on a column. The below example illustrates both use cases.

.. code-block:: python

from __future__ import annotations
from sqlalchemy import Column, String
from sqlalchemy.ext.declarative import declarative_base
from mock_alchemy.mocking import UnifiedAlchemyMagicMock
Expand All @@ -144,28 +146,43 @@ To do this you must create another object to represent the returned attribute (i
pkey = Column(String, primary_key=True)
col1 = Column(String(50))

class SingleColumn(Base):
"""SQLAlchemy object for mocking a query for a specific column."""
__tablename__ = "column"
col1 = Column(String(50), primary_key=True)
def __eq__(self, other: Model) -> bool:
"""Object equality checker."""
if isinstance(other, SomeTable):
return self.pkey == other.pkey and self.col1 == other.col1
return NotImplemented

col1_val = "val"
row1 = SomeTable(pkey=1, col1=col1_val)
mock_session = UnifiedAlchemyMagicMock(
data=[
(
[
mock.call.query(SomeTable.col1),
mock.call.filter(SomeTable.pkey == 3),
mock.call.filter(SomeTable.pkey == 1),
],
[SingleColumn(col1="test")],
)
[(col1_val,)],
),
(
[
mock.call.query(SomeTable),
mock.call.filter(SomeTable.pkey == 1),
],
[row1],
),
]
)
found_col1 = (
mock_session.query(SomeTable.col1)
.filter(SomeTable.pkey == 3)
.scalar()
)
assert found_col1 == "test"

#### Selecting on a column and using scalar()

found_col1 = mock_session.query(SomeTable.col1).filter(SomeTable.pkey == 1).scalar()
assert col1_val == found_col1

#### Selecting on a table and using scalar()

found_row = mock_session.query(SomeTable).filter(SomeTable.pkey == 1).scalar()
assert row1 == found_row


Deleting in Sessions
++++++++++++++++++++
Expand Down
Loading