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

Rc/5.1.1 #735

Merged
merged 49 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1f58716
Add impersonation and tests
Jul 20, 2023
a4d3834
Fix SonarQube bugs
Jul 20, 2023
b31f416
Merge remote-tracking branch 'origin/master' into housekeeping/sonarq…
Jul 20, 2023
47ba190
Update core with SonarQube codesmells
Jul 20, 2023
ce726f1
More SQ fixes
Jul 20, 2023
4fb1cf9
Fix SonarQube code smells
Jul 20, 2023
4209a9e
Fix syntax not available in Python <3.10
Jul 20, 2023
814014d
Merge pull request #726 from neo4j-contrib/housekeeping/sonarqube-imp…
mariusconjeaud Jul 21, 2023
627c34d
Add docs
Jul 21, 2023
4491e62
Update test
Jul 21, 2023
9814c0e
Merge pull request #724 from neo4j-contrib/feature/impersonation
mariusconjeaud Jul 31, 2023
ca78d04
Update tags to 5.1.1
Aug 1, 2023
5f710d3
Updated neomodel.db.set_connection so that it does not fail when sett…
aanastasiou Aug 1, 2023
df62ba4
Merge branch 'rc/5.1.1' into fix_init_con_bug
mariusconjeaud Aug 2, 2023
2b0c28e
Merge pull request #730 from aanastasiou/fix_init_con_bug
mariusconjeaud Aug 2, 2023
86cd931
Improved the documentation of the neomodel_(install|remove)_labels.py…
aanastasiou Aug 2, 2023
5e62d7e
Get database edition when getting version and skip tests which will f…
Aug 2, 2023
cd3b611
Add 4.4 community to test matrix
Aug 2, 2023
9ebeed2
Skip impersonation tests on community
Aug 2, 2023
641aed5
Fix pytest skipif - Missing reason info
Aug 2, 2023
c9461d9
Disable impersonation for community edition - not supported
Aug 2, 2023
7c91b6b
Add a test for not supported feature
Aug 2, 2023
cb7da6e
Fix warning
Aug 2, 2023
9061c18
Reverse order of pytest skip and db.impersonate
Aug 2, 2023
c7785af
Split @db.impersonate method out of the test or it does not get skipped
Aug 2, 2023
531d8c4
Use with or test does not get skipped
Aug 2, 2023
d99902c
Merge pull request #731 from aanastasiou/improve_scripts
mariusconjeaud Aug 2, 2023
f52ab6f
Try adding neo4j watcher to get log on Aura connection test issues
Aug 3, 2023
1a04c7e
Merge pull request #733 from neo4j-contrib/feature/get-neo4j-edition
mariusconjeaud Aug 4, 2023
cab3ef4
Extract connection to prev_url into fixture
Aug 4, 2023
66f34f5
Merge pull request #734 from neo4j-contrib/tests/improve-aura-tests
mariusconjeaud Aug 4, 2023
47d7da5
Remove unnecessary driver close in test connection
Aug 4, 2023
e7b4975
Added automatic path inflation
73VW Jul 10, 2023
ec81d23
Move neo4j debug watcher into tests
Aug 21, 2023
04dc70b
Bump neo4j driver
Aug 21, 2023
a939e4c
Update changelog
Aug 21, 2023
11dbd2c
Add cache to Integration tests workflow
Aug 21, 2023
e155d93
Added relationship import mid-code :/
aanastasiou Aug 22, 2023
da411b0
Added a very simple test for paths
aanastasiou Aug 22, 2023
9c7283c
Added documentation
aanastasiou Aug 22, 2023
bd7a245
Add user agent with neomodel version tag
Aug 22, 2023
f3eb90b
Merge pull request #740 from neo4j-contrib/task/add-user-agent
mariusconjeaud Aug 22, 2023
f26481b
Restructured the path initialisation
aanastasiou Aug 23, 2023
7f416bc
Corrected bug in instantiation of NeomodelPath. It is now completely …
aanastasiou Aug 23, 2023
69242d8
Removed commented out code
aanastasiou Aug 23, 2023
3196f29
Merge branch 'rc/5.1.1' into automatic_path_inflation
mariusconjeaud Aug 23, 2023
0a85e0c
Merge pull request #738 from neo4j-contrib/automatic_path_inflation
mariusconjeaud Aug 24, 2023
9998c45
Update Changelog
Aug 24, 2023
b138b55
Fix code smell
Aug 24, 2023
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
5 changes: 3 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.11", "3.10", "3.9", "3.8", "3.7"]
neo4j-version: ["enterprise", "5.5-enterprise", "4.4-enterprise"]
neo4j-version: ["community", "enterprise", "5.5-enterprise", "4.4-enterprise", "4.4-community"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Creating Neo4j Container
run: |
chmod +x ./docker-scripts/docker-neo4j.sh
Expand Down
3 changes: 2 additions & 1 deletion .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
sonar.sources = neomodel/
sonar.tests = test/
sonar.tests = test/
sonar.python.version = 3.7, 3.8, 3.9, 3.10, 3.11
6 changes: 6 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Version 5.1.1 2023-08
* Add impersonation
* Bumped neo4j-driver to 5.11.0
* Add automatic path inflation #715
* Improve code quality and tooling

Version 5.1.0 2023-07
* Bumped neo4j-driver version to 5.10.0
* Breaking change : When using neomodel along with Neo4j version 5, use StructuredNode and StructuredRel's element_id property instead of id. If you have Cypher queries which currently use the id() function, migrate them to elementId() instead.
Expand Down
3 changes: 2 additions & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import alabaster

from neomodel import __author__, __package__, __version__
from neomodel import __author__, __package__
from neomodel._version import __version__

#
# neomodel documentation build configuration file, created by
Expand Down
4 changes: 2 additions & 2 deletions doc/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Adjust driver configuration::
config.MAX_TRANSACTION_RETRY_TIME = 30.0 # default
config.RESOLVER = None # default
config.TRUST = neo4j.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES # default
config.USER_AGENT = None # default
config.USER_AGENT = neomodel/vNeo4j.Major.minor # default

Setting the database name, for neo4j >= 4::

Expand All @@ -38,7 +38,7 @@ constraints and indexes at compile time. However this method is only recommended
# before loading your node definitions
config.AUTO_INSTALL_LABELS = True

Neomodel also provides the `neomodel_install_labels` script for this task,
Neomodel also provides the :ref:`neomodel_install_labels` script for this task,
however if you want to handle this manually see below.

Install indexes and constraints for a single class::
Expand Down
6 changes: 3 additions & 3 deletions doc/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,16 @@ and constraints.

Applying constraints and indexes
================================
After creating a model in Python, any constraints or indexes need must be applied to Neo4j and ``neomodel`` provides a
script to automate this: ::
After creating a model in Python, any constraints or indexes must be applied to Neo4j and ``neomodel`` provides a
script (:ref:`neomodel_install_labels`) to automate this: ::

$ neomodel_install_labels yourapp.py someapp.models --db bolt://neo4j:neo4j@localhost:7687

It is important to execute this after altering the schema and observe the number of classes it reports.

Remove existing constraints and indexes
=======================================
Similarly, ``neomodel`` provides a script to automate the removal of all existing constraints and indexes from
Similarly, ``neomodel`` provides a script (:ref:`neomodel_remove_labels`) to automate the removal of all existing constraints and indexes from
the database, when this is required: ::

$ neomodel_remove_labels --db bolt://neo4j:neo4j@localhost:7687
Expand Down
40 changes: 32 additions & 8 deletions doc/source/module_documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,37 @@ Modules documentation
=====================

Database
--------
========
.. module:: neomodel.util
.. autoclass:: neomodel.util.Database
:members:
:undoc-members:

Core
----
====
.. automodule:: neomodel.core
:members:

.. _semistructurednode_doc:

``SemiStructuredNode``
^^^^^^^^^^^^^^^^^^^^^^
----------------------
.. autoclass:: neomodel.contrib.SemiStructuredNode

Properties
----------
==========
.. automodule:: neomodel.properties
:members:
:show-inheritance:

Spatial Properties & Datatypes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
------------------------------
.. automodule:: neomodel.contrib.spatial_properties
:members:
:show-inheritance:

Relationships
-------------
=============
.. automodule:: neomodel.relationship
:members:
:show-inheritance:
Expand All @@ -46,8 +46,18 @@ Relationships
:members:
:show-inheritance:

Paths
=====

.. automodule:: neomodel.path
:members:
:show-inheritance:




Match
-----
=====
.. module:: neomodel.match
.. autoclass:: neomodel.match.BaseSet
:members:
Expand All @@ -61,9 +71,23 @@ Match


Exceptions
----------
==========

.. automodule:: neomodel.exceptions
:members:
:undoc-members:
:show-inheritance:

Scripts
=======

.. automodule:: neomodel.scripts.neomodel_install_labels
:members:
:undoc-members:
:show-inheritance:

.. automodule:: neomodel.scripts.neomodel_remove_labels
:members:
:undoc-members:
:show-inheritance:

54 changes: 54 additions & 0 deletions doc/source/queries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,57 @@ For random ordering simply pass '?' to the order_by method::

Coffee.nodes.order_by('?')

Retrieving paths
================

You can retrieve a whole path of already instantiated objects corresponding to
the nodes and relationship classes with a single query.

Suppose the following schema:

::

class PersonLivesInCity(StructuredRel):
some_num = IntegerProperty(index=True,
default=12)

class CountryOfOrigin(StructuredNode):
code = StringProperty(unique_index=True,
required=True)

class CityOfResidence(StructuredNode):
name = StringProperty(required=True)
country = RelationshipTo(CountryOfOrigin,
'FROM_COUNTRY')

class PersonOfInterest(StructuredNode):
uid = UniqueIdProperty()
name = StringProperty(unique_index=True)
age = IntegerProperty(index=True,
default=0)

country = RelationshipTo(CountryOfOrigin,
'IS_FROM')
city = RelationshipTo(CityOfResidence,
'LIVES_IN',
model=PersonLivesInCity)

Then, paths can be retrieved with:

::

q = db.cypher_query("MATCH p=(:CityOfResidence)<-[:LIVES_IN]-(:PersonOfInterest)-[:IS_FROM]->(:CountryOfOrigin) RETURN p LIMIT 1",
resolve_objects = True)

Notice here that ``resolve_objects`` is set to ``True``. This results in ``q`` being a
list of ``result, result_name`` and ``q[0][0][0]`` being a ``NeomodelPath`` object.

``NeomodelPath`` ``nodes, relationships`` attributes contain already instantiated objects of the
nodes and relationships in the query, *in order of appearance*.

It would be particularly useful to note here that each object is read exactly once from
the database. Therefore, nodes will be instantiated to their neomodel node objects and
relationships to their relationship models *if such a model exists*. In other words,
relationships with data (such as ``PersonLivesInCity`` above) will be instantiated to their
respective objects or ``StrucuredRel`` otherwise. Relationships do not "reload" their
end-points (unless this is required).
36 changes: 36 additions & 0 deletions doc/source/transactions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,39 @@ or manually::
bookmark = db.commit()
except Exception as e:
db.rollback()

Impersonation
-------------

*Neo4j Enterprise feature*

Impersonation (`see Neo4j driver documentation <https://neo4j.com/docs/api/python-driver/current/api.html#impersonated-user-ref>``)
can be enabled via a context manager::

from neomodel import db

with db.impersonate(user="writeuser"):
Person(name='Bob').save()

or as a function decorator::

@db.impersonate(user="writeuser")
def update_user_name(uid, name):
user = Person.nodes.filter(uid=uid)[0]
user.name = name
user.save()

This can be mixed with other context manager like transactions::

from neomodel import db

@db.impersonate(user="tempuser")
# Both transactions will be run as the same impersonated user
def func0():
@db.transaction()
def func1():
...

@db.transaction()
def func2():
...
2 changes: 1 addition & 1 deletion neomodel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
)
from .relationship import StructuredRel
from .util import change_neo4j_password, clear_neo4j_database
from .path import NeomodelPath

__author__ = "Robin Edwards"
__email__ = "robin.ge@gmail.com"
__license__ = "MIT"
__package__ = "neomodel"
__version__ = "5.1.0"
1 change: 1 addition & 0 deletions neomodel/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "5.1.1"
4 changes: 3 additions & 1 deletion neomodel/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import neo4j

from ._version import __version__

AUTO_INSTALL_LABELS = False
DATABASE_URL = "bolt://neo4j:foobarbaz@localhost:7687"
FORCE_TIMEZONE = False
Expand All @@ -13,4 +15,4 @@
MAX_TRANSACTION_RETRY_TIME = 30.0
RESOLVER = None
TRUSTED_CERTIFICATES = neo4j.TrustSystemCAs()
USER_AGENT = None
USER_AGENT = f"neomodel/v{__version__}"
Loading
Loading