Commit Graph

5398 Commits

Author SHA1 Message Date
Paolo Tosco
1cd5b24e43 - str_to_c() should initialize len to 0 even if memory allocation fails (#8112)
- str_to_c() should check the ptr returned by malloc for non-nullness before using it
- change has_coords() mol_pkl parameter to const
- use assert.equal in JS tests where possible

Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-12-19 06:04:00 +01:00
Greg Landrum
e77d4e3f6a allow specified chiral features to SSS match unspecified features (#8115) 2024-12-18 20:37:17 +01:00
Paolo Tosco
74fc77f959 normalizeDepiction() should always center coordinates on the coordinate centroid, irrespective of the canonicalize parameter (#8107)
* normalizeDepiction() should always center coordinates on the coordinate centroid, irrespective of the canonicalize parameter

* Update Code/GraphMol/Depictor/catch_tests.cpp

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>

* fix catch test

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-12-18 13:40:57 +01:00
David Cosgrove
e589f173fd Use endian-aware read/write for length of string. (#8105)
* Use endian-aware read/write for length of string.

* Re-run clang-format.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-18 05:14:11 +01:00
David Cosgrove
ce35b3c25b SynthonSearch synth check (#8109)
* Catch errors when creating products.

* Extra python test.

* Fix formatting.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-18 05:12:07 +01:00
Nikitas Rontsis
e640915d4e Avoid unnecessary matching (#8111) 2024-12-17 16:11:40 +01:00
David Cosgrove
736e309f10 Fix empty results bug. (#8099)
Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-14 18:21:29 +01:00
Greg Landrum
c90cee9b77 Add Molecular Interaction Fields (#7993)
* Add RealValueVect.

* Add UniformRealValueGrid3D

* Add Molecular Interaction Fields (MIFs)

* line endings

* cherry-pick f1bc94a4c8

* format

* Adapt tests for python3.

* Adapt RealValueVector pickling for python3.

* Speed-up of MIF calculations.

* Bugfix in MIFDescriptors.cpp.

* all tests pass

* clean up some memory leaks

* update copyrights

* rename

* rename the library

* complete the rename

* lost file

* another forgotten file

* cleanup

* clang-tidy

* clang-tidy

* windows DLL builds work

* python wrapper and tests cleanup

* convert to catch2 testing

* switch RealValueVect to use std::vector

* remove obsolete friend

* - Replace explicit loops with stdlib implicit equivalents
- Replace explicit types with auto where possible
- Avoid unnecessary copy operations where possible
- Replace raw pointers with exception-safe unique_ptr
- Replace C-style #define with constexpr
- Replace C-style casts with C++ casts
- Replace C-style arrays with std::vector
- Avoid code duplication with templated operators
- Replace VdWaals class taking multiple atom type definitions and force-field name as string parameter with force-field-specific classes deriving from an abstract VdWaals class
- Replace x,y,z doubles with Point3D class where possible
- Removed unused (and untested) DistanceToClosestAtom class
- Renamed some variables and functions for better clarity
- Converted tabs to spaces
- Made the mol parameter in cube read/write functions optional for convenience
- Made the Python wrappers more pythonic (e.g., avoid C++-style passing objects as parameters which are modified in place)
- Implemented alternative Python class constructors using boost::python::make_constructor rather than with external non-class functions
- The Python wrappers taking a sequence of Point3D now take a sequence of sequences, such that the output of Conformer.GetPositions() can be passed
- Made the Python wrapper sequence parsing more robust
- Removed duplicated code from Python wrappers

* - avoid an unnecessary copy

* progress

* works

* more cleanup

* all tests pass

* changes in response to review

---------

Co-authored-by: dfhahn <dfhahn@users.noreply.github.com>
Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-12-14 17:08:43 +01:00
David Cosgrove
6db3f982cb Allow fragments of aromatic rings to match in RascalMCES (#8088)
* Allow fragments of aromatic rings to match.

* Use existing code for checking bond is in ring.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-13 07:20:24 +01:00
David Cosgrove
403cd55e6a Synthon search fp bug (#8086)
* Fix bug - connector patterns weren't being matched to the synthon connector patterns.

* Tiny tweak.

* Typo in comment.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-12 18:24:01 +01:00
Greg Landrum
607912a579 fixes #8060 (#8087)
* fixes #8060

* check the new stereo code too
2024-12-12 18:13:29 +01:00
Paolo Tosco
a6654c4f8f Make sure that loggers can be enabled, disabled, captured and tee'd from MinimalLib (#7962)
* make sure that loggers can be enabled, disabled, captured and tee'd from MinimalLib without issues

* changes in response to review

* change in response to review

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-12-12 13:44:33 +01:00
Paolo Tosco
4431fb708c avoid that map::at() throws an exception in case atomColourPalette includes neither 6 nor -1 (#8085)
Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-12-12 06:13:52 +01:00
Ricardo Rodriguez
c01ca64ac1 Fixes #8065 (#8066)
* add test + fix

* simplification

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>

---------

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-12-12 06:11:23 +01:00
David Cosgrove
578b56a7c5 Resolve clashing atom labels in 2D drawing (#8074)
* Move atom labels round if they clash.

* Tidy.

* Re-work orientation logic.
Remove virtual fns from AtomSymbol.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-12-11 09:25:17 +01:00
David Cosgrove
d985a44f26 Handle DOS files in SynthonSpaceSearch (#8075)
* Handle DOS files.

* Smaller test file.
Add DOS file to .gitattributes.

* Update Code/GraphMol/SynthonSpaceSearch/substructure_search_catch_tests.cpp

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-12-09 17:29:17 +01:00
Brian Kelley
bd85b29d43 Fix #4570 Segfault on Property Getters/Setters (#8042)
* Fix #4570 Segfault on Property Getters/Setters

* Revert regression, response to review

* Remove print statement
2024-12-09 14:34:40 +01:00
Paolo Tosco
bd8289738d Fix #8027 (#8031)
* - Fix #8029
- avoid unnecessary rounding errors in the JSON writer
- remove a warning when compiling MinimalLib without SubstructLIbrary support

* changes in response to review

* changes in response to review

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-11-30 07:20:20 +01:00
David Cosgrove
bbac292b4c Synthon fingerprint search (#8025)
* First pass at splitting molecule.

* Interim commit.  Reading libraries from file in original format.

* Basic search seems to be working.

* Pattern fingerprint screening.

* Connector region heuristic.

* Fixed triazole (aromatic/non-aromatic connectors).

* Fix search with non-split parent query, where query is substructure of a single reagent.

* Remove duplicate hits by reaction/reagents used.

* Implement largest fragment heuristic.

* Extra test files.

* Read/write binary file.
Program for conversion from text format to binary format.

* Remove empty reagent sets on reading, probably due to synthon number counting from 1 rather than 0.

* Tidy SSSearch functions.

* Stash pending major surgery for triazole bug.

* Revert to using unique_ptr.
Correct use of reagent order.

* Function to summarise Hyperspace.

* Delay building hits till end and put cutoff on number.

* Earlier bale-out in getHitReagents.

* Streamline checkConnectorRegions.

* Remove free functions for search.

* Correct name of Python test.

* First stage of Python wrappers.

* Rename namespace.

* Parameters object.

* Mysterious windows export thing.

* Fix bug - not matching number of connectors in fragment and synthon.

* Back like it was.  The connector count wasn't the problem.

* Put the substructure results into their own class.

* gcc 14 didn't like my use of std::reduce.
Update expected test results.

* Remove write statement.

* Tidy.

* Tidy.

* Enable random sample of hits.

* Test that complex SMARTS works.
Update Python wrappers.

* Rename Hyperspace to SynthonSpace.

* More renaming.
Python test.

* Enable Python test.
Remove write.

* Plug memory leak.

* Response to Greg's initial look.

* More response to Greg's initial look.

* get the windows DLL builds working

* Do away with mutable.
Purge a few more uses of reagent in favour of synthon.
Remove the c++ exe for converting text to binary databases.

* Better Synthon c'tor.

* More feedback from Greg.

* Tidy the Python wrapper.

* Remove tags from catch tests.

* Don't allow copying of SubstructureResults.

* Revert to allow copying of SubstructureResults.  The Python wrapper needs it.

* Refinements based on CLion/clangd suggestions.

* Allow for map numbers in connectors in space file.

* Refactor to make the searcher a separate class from the space.

* Transfer Greg's review suggestions from Hyperspace merge.

* First cut of fingerprint searcher.

* Python wrapper.
Some tidying.

* Better random selection.

* Fix bug in preparing frags for fingerprints.
Re-factor.

* Minor-refactor.

* Sort hits by similarity if available.

* Option for a few different fingerprint types.  Pending a better solution.

* Write fingerprints to binary file.

* Use any fingerprint generator for similarity searching.  No Python wrapper yet.

* Python wrapper.

* Change random selection to use distribution weighted by number of hits in each reaction.

* Lots of suggestions from CLion/clang.

* Use boost discrete_distribution for cross-platform consistency.

* Tidy test up.

* Try boost rng as well.

* uniform_int_distribution to boost also.

* Small tidy.

* Method to write enumerated library.

* Windows export thing.

* Windows export thing.

* Allow for commas in tab-separated fields.

* win64 dll builds now work

* More aliphatic synthon, aromatic product joy.

* Force ring finding if it hasn't been done.

* Fingerprint hits not being sorted if maxHits reached.

* Remove debugging write.  Doh!

* Response to review of SynthonSpace2.

* Missed one.

* Add test file.

* Hand merge Greg's #8050.

* Discard nodiscard.

* Move include of export.h inside include guards.

* Response to review.

* Fix memory leaks.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-11-29 13:07:32 +01:00
David Cosgrove
8b7f773593 Improve doc string for ParseAbbreviations in python wrapper. (#8049)
Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-11-28 13:54:04 +01:00
David Cosgrove
43229cf933 Synthon space2 (#8048)
* Fix for connector regions and missing ringinfo.

* Merge in the fix for comma-separated names in tab-separated space files.

* Response to review.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
2024-11-28 13:12:35 +01:00
Dan Nealschneider
003225206d Remove explicit default constructor from Compute2DCoordParameters (#8046)
The explicit default constructor actually blocks the other
defaults. It also means this is no longer a "plain struct",
and so designated initializers aren't available.

I wanna be able to do:

    Compute2DCoordParameters params{.useRingTemplates = true};

Or even:

    RDDepict::compute2DCoords(*mol, {.useRingTemplates = true};
2024-11-28 08:29:44 +01:00
Eric Boittier
64fcea7391 [fix] issue #7572, precondition rootAtAtom if more than one fragment exists (#7811)
* [fix] re: issue #7572; added precondition check to prevent setting a root atom when more than one fragment exists

* tests for #7572, precondition rootAtAtom if more than one fragment exists

* test the fix to issue #7572

* [fix] moved the precondition to a block which get atom at index to prevent unhandled exceptions, MHFP tests pass now

---------

Co-authored-by: Eric Boittier <ericdavid.boittier@unibas.ch>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-11-28 07:06:44 +01:00
Brian Kelley
7b31d5307b MergeQueryHs better detects hydrogens in OR queries (#8043)
* Fixes #7687

* Make sure high and low precedence ands also work

* really fix the issue

* Fix merge conflict

* Add AtomType to MergeH check with test
2024-11-26 04:44:32 +01:00
Ricardo Rodriguez
1b0a20c372 Fix shifting of a potentially negative number (#8014)
* fix shifting a potentially negative number

* add a test

* fix signed comparison
2024-11-24 06:50:16 +01:00
Greg Landrum
a0a21e6ec6 Fixes #8023 (#8024) 2024-11-21 14:28:19 +01:00
Paolo Tosco
fc6e37d11e fix #8019 (#8020)
Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-11-20 09:09:56 +01:00
Ricardo Rodriguez
db0df54347 Fix some minor issues reported by ubsan and the compiler (#8015)
* initialize chiralityPossible

* fix build warning

* Fix integer overflow

* fix downcasting MarvinMolBase to MarvinMol

* Fix buildwarning

* increase PairList container to 64 bit

* fix testDict

* Update Code/RDGeneral/testDict.cpp

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>

* Update Code/GraphMol/CIPLabeler/rules/Pairlist.h

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>

* Update Code/GraphMol/CIPLabeler/rules/Pairlist.h

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>

* Fix catch_tests.cpp

---------

Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-11-20 09:09:22 +01:00
Ivan Tubert-Brohman
d8bc5d61f8 Catch exceptions in MultithreadedMolSupplier callbacks (#7810)
* Catch exceptions in MultithreadedMolSupplier callbacks

* In next(), simply ignore any exceptions from nextCallback.
* In reader(), if readCallback throws, log a warning and proceed using
  the unmodified record.
* (The writer() was already handling exceptions from writeCallback.)

* Remove unused parameter names

Hopefully this will placate the warning/error settings used by the Linux
build.
2024-11-19 17:22:25 +01:00
Ricardo Rodriguez
39d4662ae7 Throw when attempting to normalize a Zero RDGeom::Point (#8008)
* throw if close to zero

* fix moldraw2DTestCatch

* Fix testRGroupDecomp

* fix one test in distGeomHelpersCatch

* fix tests in distGeomHelpersCatch

* retry finding a dir vector when adding Hs

* push UFF fixes to calculateCosY

* fix the setTerminalAtomCoords deg 4 patch

* add a test

* reduce zero tolerance
2024-11-19 04:33:22 +01:00
Ricardo Rodriguez
ffb100d928 avoid division by zero (#8013) 2024-11-19 04:32:44 +01:00
Hussein Faara
f35e7e6414 remove no-op macros and dead code (pt 1) (#8012) 2024-11-19 04:31:56 +01:00
David Cosgrove
eaf544ab6f SynthonSpace Search (#7978)
* First pass at splitting molecule.

* Interim commit.  Reading libraries from file in original format.

* Basic search seems to be working.

* Pattern fingerprint screening.

* Connector region heuristic.

* Fixed triazole (aromatic/non-aromatic connectors).

* Fix search with non-split parent query, where query is substructure of a single reagent.

* Remove duplicate hits by reaction/reagents used.

* Implement largest fragment heuristic.

* Extra test files.

* Read/write binary file.
Program for conversion from text format to binary format.

* Remove empty reagent sets on reading, probably due to synthon number counting from 1 rather than 0.

* Tidy SSSearch functions.

* Stash pending major surgery for triazole bug.

* Revert to using unique_ptr.
Correct use of reagent order.

* Function to summarise Hyperspace.

* Delay building hits till end and put cutoff on number.

* Earlier bale-out in getHitReagents.

* Streamline checkConnectorRegions.

* Remove free functions for search.

* Correct name of Python test.

* First stage of Python wrappers.

* Rename namespace.

* Parameters object.

* Mysterious windows export thing.

* Fix bug - not matching number of connectors in fragment and synthon.

* Back like it was.  The connector count wasn't the problem.

* Put the substructure results into their own class.

* gcc 14 didn't like my use of std::reduce.
Update expected test results.

* Remove write statement.

* Tidy.

* Tidy.

* Enable random sample of hits.

* Test that complex SMARTS works.
Update Python wrappers.

* Rename Hyperspace to SynthonSpace.

* More renaming.
Python test.

* Enable Python test.
Remove write.

* Plug memory leak.

* Response to Greg's initial look.

* More response to Greg's initial look.

* get the windows DLL builds working

* Do away with mutable.
Purge a few more uses of reagent in favour of synthon.
Remove the c++ exe for converting text to binary databases.

* Better Synthon c'tor.

* More feedback from Greg.

* Tidy the Python wrapper.

* Remove tags from catch tests.

* Don't allow copying of SubstructureResults.

* Revert to allow copying of SubstructureResults.  The Python wrapper needs it.

* Refinements based on CLion/clangd suggestions.

* Allow for map numbers in connectors in space file.

* Response to review.

* update binary file spec

* Changes after review.

---------

Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-11-17 08:13:54 +01:00
Ricardo Rodriguez
ff93b2919f look at y if x is very small (#8011) 2024-11-17 06:22:25 +01:00
Paolo Tosco
8c1bf34ed7 implemented JSON parsers for SanitizeFlags and RemoveHsParameters for CFFI and MinimalLib (#8000)
Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-11-16 05:16:25 +01:00
Ricardo Rodriguez
999d9097c1 fix potential division by zero (#8007) 2024-11-15 16:16:29 +01:00
Brian Kelley
9495dd5413 Expose tautomer scoring functions to python (#7994)
* Expose tautomer scoring functions to python

* Add more tests/documentation

* Rename getDefaultTautomerSubstructs to getDefaultTautomerScoreSubstructs

* Remove ROMOL_SPTR

* Add full custom scoring function example

* Run clang format

* Use proper BOOST_PYTHON_FUNCTION_OVERLOADS

* Use default copy constructor
2024-11-15 05:37:35 +01:00
tadhurst-cdd
c2168cd8be Fix for kekuleAtrop wedge error (#7992)
* Fix for kekuleAtrop error

* Consolodate repeating code in new tests

* as per PR review - simplification
2024-11-15 04:39:38 +01:00
David Cosgrove
1aa30412cd Mol to smiles docs (#8005)
* Use new Morgan fingerprint generator.

* Add script to build fragments database and amend score script to use it.

* Remove redundant imports.

* Response to review.

* Clarify interaction of canonical and random in MolToSmiles.

---------

Co-authored-by: Dave Cosgrove <david@cozchemix.co.uk>
2024-11-14 15:34:30 +01:00
Greg Landrum
7872341b92 fixes #8001 (#8002) 2024-11-14 05:14:51 +01:00
Paolo Tosco
9c63cf6c54 Expose molzip functionality to MinimalLib (#7959)
* Expose molzip functionality to MinimalLib

* changes from code review

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
2024-11-12 17:16:14 +01:00
Hussein Faara
9db22a9178 Update SMILES parsing syntax error to include bad token position (#7979)
* Implements #TODO

This attempts to improve the SMILES parsing procedure to provide more
information about bad inputs by pointing to general location of the offending token.
The improved error messages currently only apply to syntax errors, inputs with
extra close parentheses, and inputs with too large numbers, but this will
provide a way to extend that in the future

Some examples of the improved error messages

| old version                            | new version            |
|----------------------------------------|------------------------|
|syntax error while parsing: c%()ccccc%() | syntax error while parsing input:<br /> `c%()ccccc%()` <br /> `~~~^` |
|syntax error while parsing: c%(100000)ccccc%(100000) | syntax error while parsing input: <br /> `c%(100000)ccccc%(100000)` <br /> `~~~~~~~~^` |
|syntax error while parsing: COc(c1)cccc1C#|syntax error while parsing input: <br /> `COc(c1)cccc1C#` <br /> `~~~~~~~~~~~~~^` |
|extra close parentheses while parsing: C) | extra close parentheses while parsing input: <br /> `C)` <br /> `~^` |
| extra close parentheses while parsing: C1C)foo | extra close parentheses while parsing input: <br /> `C1C)foo` <br /> `~~~^` |
| number too large while parsing: [555555555555555555C] | number too large while parsing input: <br /> `[555555555555555555C]` <br /> `~~~~~~~~~~^` |

This was achieves by extending the lexing and parsing procedure to track
the current token position with a new variable, so the reported position
may not be 100% accurate at all times but should be helpful in reducing
the amount of work done to find the bad location.

Additionally, I updated the build instructions to strip the #line macros
from the generated C++ files, which required a modern flex/bison
versions.

* fix build failure on windows

* static vars are not captured implicitly

* copy generated files to fix windows build failure

* fix long input truncation

* copied the wrong files again :(

* Review suggestions

* update error messges for extra open brackets

These aere example error messages:

```
[09:54:03] SMILES Parse Error: extra open parentheses while parsing: C1CC1(CC
[09:54:03] SMILES Parse Error: check for mistakes around position 6:
[09:54:03] C1CC1(CC
[09:54:03] ~~~~~^

[09:54:03] SMILES Parse Error: Failed parsing SMILES 'C1CC1(CC' for input: 'C1CC1(CC'
[09:54:03] SMILES Parse Error: extra open parentheses while parsing: C1CC1(CC(CC
[09:54:03] SMILES Parse Error: check for mistakes around position 6:
[09:54:03] C1CC1(CC(CC
[09:54:03] ~~~~~^

[09:54:03] SMILES Parse Error: extra open parentheses while parsing: C1CC1(CC(CC
[09:54:03] SMILES Parse Error: check for mistakes around position 9:
[09:54:03] C1CC1(CC(CC
[09:54:03] ~~~~~~~~^
```

* fix bad merge artefact.
2024-11-12 14:47:15 +01:00
Hussein Faara
384e296ba0 Remove unused code from GraphMol/SmilesParse (#7996) 2024-11-11 05:58:12 +01:00
tadhurst-cdd
57a9d2928f Fix incorrect CIP values for some aromatic atropisomers (#7957) 2024-11-09 10:32:46 +01:00
Brian Kelley
75e8858a93 Fixes #7989 Incorrect benzyl deprotection reaction (#7990) 2024-11-07 18:34:59 +01:00
tadhurst-cdd
649a62a39d Fix for trimethylcyclohexane error (#7949) 2024-11-07 06:15:32 +01:00
Paolo Tosco
b1d322555b Expose propertyFlags to CFFI and MinimalLib (#7960)
* - added property support to CFFI library
- added propertyFlags JSON parser
- added support for setting propertyFlags to MinimalLib

* added missing files

* fix SWIG builds

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
2024-11-07 06:08:27 +01:00
Greg Landrum
5b943e3a55 Fixed #7986 (#7987)
* Fixed #7986

* get builds working on linux

* try again

* oops, use std::uint32_t
2024-11-05 13:58:48 -05:00
Michael Cho
b16b6026e8 Use .dylib on macOS for PostgreSQL 16+ (#7869)
See b55f62abb2
2024-11-01 06:18:02 +01:00
Greg Landrum
2f119c2693 Convert reaction fingerprinter to use FingerprintGenerators (#7931)
* FingerprintGenerator improvements

1. simplify construction by adding ctors taking FingerprintArguments
2. remove inexplicable boost::noncopyable from FingerprintArguments

* Switch FingerprintType to be an enum class

* Fixes #7521

* dumb mistake

* initialize everything

* get the defaults right

* Update Code/GraphMol/ChemReactions/ReactionFingerprints.cpp

Co-authored-by: Paolo Tosco <paolo.tosco.mail@gmail.com>

---------

Co-authored-by: Paolo Tosco <paolo.tosco.mail@gmail.com>
2024-10-31 06:58:02 +01:00