Skip to content

Commit

Permalink
Merge pull request #735 from neo4j-contrib/rc/5.1.1
Browse files Browse the repository at this point in the history
Rc/5.1.1
  • Loading branch information
mariusconjeaud authored Aug 24, 2023
2 parents f4d4a72 + b138b55 commit 823dc4a
Show file tree
Hide file tree
Showing 32 changed files with 956 additions and 338 deletions.
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__ = "[email protected]"
__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

0 comments on commit 823dc4a

Please sign in to comment.