├── .gitignore
├── BACKERS.md
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs
└── README
├── pony
├── __init__.py
├── converting.py
├── flask
│ ├── __init__.py
│ └── example
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── app.py
│ │ ├── config.py
│ │ ├── models.py
│ │ ├── templates
│ │ ├── index.html
│ │ ├── login.html
│ │ └── reg.html
│ │ └── views.py
├── javascript
│ └── pony.js
├── options.py
├── orm
│ ├── __init__.py
│ ├── asttranslation.py
│ ├── core.py
│ ├── dbapiprovider.py
│ ├── dbproviders
│ │ ├── __init__.py
│ │ ├── cockroach.py
│ │ ├── mysql.py
│ │ ├── oracle.py
│ │ ├── postgres.py
│ │ └── sqlite.py
│ ├── dbschema.py
│ ├── decompiling.py
│ ├── examples
│ │ ├── __init__.py
│ │ ├── bottle_example.py
│ │ ├── compositekeys.py
│ │ ├── demo.py
│ │ ├── estore.py
│ │ ├── inheritance1.py
│ │ ├── numbers.py
│ │ ├── university1.py
│ │ └── university2.py
│ ├── integration
│ │ ├── __init__.py
│ │ └── bottle_plugin.py
│ ├── ormtypes.py
│ ├── serialization.py
│ ├── sqlbuilding.py
│ ├── sqlsymbols.py
│ ├── sqltranslation.py
│ └── tests
│ │ ├── __init__.py
│ │ ├── aggregate_count_queries.txt
│ │ ├── coverage.bat
│ │ ├── coverage.sh
│ │ ├── fixtures.py
│ │ ├── model1-database.sql
│ │ ├── model1.py
│ │ ├── poster_queries.txt
│ │ ├── queries.txt
│ │ ├── sql_tests.py
│ │ ├── test_array.py
│ │ ├── test_attribute_options.py
│ │ ├── test_autostrip.py
│ │ ├── test_buffer.py
│ │ ├── test_bug_170.py
│ │ ├── test_bug_182.py
│ │ ├── test_bug_331.py
│ │ ├── test_bug_386.py
│ │ ├── test_cascade.py
│ │ ├── test_cascade_delete.py
│ │ ├── test_collections.py
│ │ ├── test_conversions.py
│ │ ├── test_core_find_in_cache.py
│ │ ├── test_core_multiset.py
│ │ ├── test_crud.py
│ │ ├── test_crud_raw_sql.py
│ │ ├── test_datetime.py
│ │ ├── test_db_session.py
│ │ ├── test_declarative_attr_set_monad.py
│ │ ├── test_declarative_exceptions.py
│ │ ├── test_declarative_func_monad.py
│ │ ├── test_declarative_join_optimization.py
│ │ ├── test_declarative_object_flat_monad.py
│ │ ├── test_declarative_orderby_limit.py
│ │ ├── test_declarative_query_set_monad.py
│ │ ├── test_declarative_sqltranslator.py
│ │ ├── test_declarative_sqltranslator2.py
│ │ ├── test_declarative_strings.py
│ │ ├── test_decompiler.py
│ │ ├── test_deduplication.py
│ │ ├── test_diagram.py
│ │ ├── test_diagram_attribute.py
│ │ ├── test_diagram_keys.py
│ │ ├── test_distinct.py
│ │ ├── test_entity_init.py
│ │ ├── test_entity_proxy.py
│ │ ├── test_exists.py
│ │ ├── test_f_strings.py
│ │ ├── test_filter.py
│ │ ├── test_flush.py
│ │ ├── test_frames.py
│ │ ├── test_generator_db_session.py
│ │ ├── test_get_pk.py
│ │ ├── test_getattr.py
│ │ ├── test_hooks.py
│ │ ├── test_hybrid_methods_and_properties.py
│ │ ├── test_indexes.py
│ │ ├── test_inheritance.py
│ │ ├── test_inner_join_syntax.py
│ │ ├── test_int_converter.py
│ │ ├── test_interleave.py
│ │ ├── test_isinstance.py
│ │ ├── test_json.py
│ │ ├── test_lambda.py
│ │ ├── test_lazy.py
│ │ ├── test_list_monad.py
│ │ ├── test_mapping.py
│ │ ├── test_objects_to_save_cleanup.py
│ │ ├── test_prefetching.py
│ │ ├── test_prop_sum_orderby.py
│ │ ├── test_query.py
│ │ ├── test_random.py
│ │ ├── test_raw_sql.py
│ │ ├── test_relations_m2m.py
│ │ ├── test_relations_one2many.py
│ │ ├── test_relations_one2one1.py
│ │ ├── test_relations_one2one2.py
│ │ ├── test_relations_one2one3.py
│ │ ├── test_relations_one2one4.py
│ │ ├── test_relations_symmetric_m2m.py
│ │ ├── test_relations_symmetric_one2one.py
│ │ ├── test_seeds.py
│ │ ├── test_select_from_select_queries.py
│ │ ├── test_show.py
│ │ ├── test_sqlbuilding_formatstyles.py
│ │ ├── test_sqlbuilding_sqlast.py
│ │ ├── test_sqlite_shared_memory_db.py
│ │ ├── test_sqlite_str_functions.py
│ │ ├── test_time_parsing.py
│ │ ├── test_to_dict.py
│ │ ├── test_tracked_value.py
│ │ ├── test_transaction_lock.py
│ │ ├── test_validate.py
│ │ ├── test_volatile.py
│ │ └── testutils.py
├── py23compat.py
├── thirdparty
│ ├── __init__.py
│ └── decorator.py
└── utils
│ ├── __init__.py
│ ├── properties.py
│ └── utils.py
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.sqlite
3 | .idea
4 | pony/orm/tests/.coverage
5 | pony/orm/tests/coverage.bat
6 | pony/orm/tests/htmlcov/*.*
7 | MANIFEST
8 | docs/_build/
9 | pony.egg-info/
10 |
--------------------------------------------------------------------------------
/BACKERS.md:
--------------------------------------------------------------------------------
1 | # Sponsors & Backers
2 |
3 | Pony ORM is Apache 2.0 licensed open source project. If you would like to support Pony ORM development, please consider:
4 |
5 | [Become a backer or sponsor](https://ponyorm.org/donation.html)
6 |
7 | ## Backers
8 |
9 | - [Vincere](https://vince.re)
10 | - Sergio Aguilar Guerrero
11 | - David ROUBLOT
12 | - Elijas Dapšauskas
13 | - Dan Swain
14 | - Christian Macht
15 | - Johnathan Nader
16 | - Andrei Rachalouski
17 | - Juan Pablo Scaletti
18 | - Marcus Birkenkrahe
19 | - Vincent Le Goff
20 | - Niklas Rosenstein
21 | - Xucong Zhan
22 | - Christian Does
23 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include pony/orm/tests/queries.txt
2 | include pony/flask/example/templates *.html
3 | include LICENSE
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Downloads
2 | [](https://pepy.tech/project/pony) [](https://pepy.tech/project/pony/month) [](https://pepy.tech/project/pony/week)
3 |
4 |
5 | Pony Object-Relational Mapper
6 | =============================
7 |
8 | Pony is an advanced object-relational mapper. The most interesting feature of Pony is its ability to write queries to the database using Python generator expressions and lambdas. Pony analyzes the abstract syntax tree of the expression and translates it into a SQL query.
9 |
10 | Here is an example query in Pony:
11 |
12 | ```python
13 | select(p for p in Product if p.name.startswith('A') and p.cost <= 1000)
14 | ```
15 |
16 | Pony translates queries to SQL using a specific database dialect. Currently Pony works with SQLite, MySQL, PostgreSQL and Oracle databases.
17 |
18 | By providing a Pythonic API, Pony facilitates fast app development. Pony is an easy-to-learn and easy-to-use library. It makes your work more productive and helps to save resources. Pony achieves this ease of use through the following:
19 |
20 | * Compact entity definitions
21 | * The concise query language
22 | * Ability to work with Pony interactively in a Python interpreter
23 | * Comprehensive error messages, showing the exact part where an error occurred in the query
24 | * Displaying of the generated SQL in a readable format with indentation
25 |
26 | All this helps the developer to focus on implementing the business logic of an application, instead of struggling with a mapper trying to understand how to get the data from the database.
27 |
28 | See the example [here](https://github.com/ponyorm/pony/blob/orm/pony/orm/examples/estore.py)
29 |
30 |
31 | Support Pony ORM Development
32 | ----------------------------
33 |
34 | Pony ORM is Apache 2.0 licensed open source project. If you would like to support Pony ORM development, please consider:
35 |
36 | [Become a backer or sponsor](https://ponyorm.org/donation.html)
37 |
38 |
39 | Online tool for database design
40 | -------------------------------
41 |
42 | Pony ORM also has the Entity-Relationship Diagram Editor which is a great tool for prototyping. You can create your database diagram online at [https://editor.ponyorm.com](https://editor.ponyorm.com), generate the database schema based on the diagram and start working with the database using declarative queries in seconds.
43 |
44 |
45 | Documentation
46 | -------------
47 |
48 | Documentation is available at [https://docs.ponyorm.org](https://docs.ponyorm.org)
49 | The documentation source is available at [https://github.com/ponyorm/pony-doc](https://github.com/ponyorm/pony-doc).
50 | Please create new documentation related issues [here](https://github.com/ponyorm/pony-doc/issues) or make a pull request with your improvements.
51 |
52 |
53 | License
54 | -------
55 |
56 | Pony ORM is released under the Apache 2.0 license.
57 |
58 |
59 | PonyORM community
60 | -----------------
61 |
62 | Please post your questions on [Stack Overflow](http://stackoverflow.com/questions/tagged/ponyorm).
63 | Meet the PonyORM team, chat with the community members, and get your questions answered on our community [Telegram group](https://t.me/ponyorm).
64 | Join our newsletter at [ponyorm.org](https://ponyorm.org).
65 | Reach us on [Twitter](https://twitter.com/ponyorm).
66 |
67 | Copyright (c) 2013-2022 Pony ORM. All rights reserved. info (at) ponyorm.org
68 |
--------------------------------------------------------------------------------
/docs/README:
--------------------------------------------------------------------------------
1 | See docs at https://docs.ponyorm.com
2 | The source is at https://github.com/ponyorm/pony-doc
--------------------------------------------------------------------------------
/pony/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | import os, sys
4 | from os.path import dirname
5 |
6 | __version__ = '0.7.19'
7 |
8 | def detect_mode():
9 | try: import google.appengine
10 | except ImportError: pass
11 | else:
12 | if os.getenv('SERVER_SOFTWARE', '').startswith('Development'):
13 | return 'GAE-LOCAL'
14 | return 'GAE-SERVER'
15 |
16 | try: from mod_wsgi import version
17 | except: pass
18 | else: return 'MOD_WSGI'
19 |
20 | main = sys.modules['__main__']
21 |
22 | if not hasattr(main, '__file__'): # console
23 | return 'INTERACTIVE'
24 |
25 | if os.getenv('IPYTHONENABLE', '') == 'True':
26 | return 'INTERACTIVE'
27 |
28 | if getattr(main, 'INTERACTIVE_MODE_AVAILABLE', False): # pycharm console
29 | return 'INTERACTIVE'
30 |
31 | if 'flup.server.fcgi' in sys.modules: return 'FCGI-FLUP'
32 | if 'uwsgi' in sys.modules: return 'UWSGI'
33 | if 'flask' in sys.modules: return 'FLASK'
34 | if 'cherrypy' in sys.modules: return 'CHERRYPY'
35 | if 'bottle' in sys.modules: return 'BOTTLE'
36 | return 'UNKNOWN'
37 |
38 | MODE = detect_mode()
39 |
40 | MAIN_FILE = None
41 | if MODE == 'MOD_WSGI':
42 | for module_name, module in sys.modules.items():
43 | if module_name.startswith('_mod_wsgi_'):
44 | MAIN_FILE = module.__file__
45 | break
46 | elif MODE != 'INTERACTIVE':
47 | MAIN_FILE = sys.modules['__main__'].__file__
48 |
49 | if MAIN_FILE is not None: MAIN_DIR = dirname(MAIN_FILE)
50 | else: MAIN_DIR = None
51 |
52 | PONY_DIR = dirname(__file__)
53 |
--------------------------------------------------------------------------------
/pony/flask/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | import importlib
4 |
5 | from pony.orm import db_session
6 |
7 |
8 | flask_lib = importlib.import_module('flask')
9 | request = getattr(flask_lib, 'request', None)
10 |
11 |
12 | def _enter_session():
13 | session = db_session()
14 | request.pony_session = session
15 | session.__enter__()
16 |
17 | def _exit_session(exception):
18 | session = getattr(request, 'pony_session', None)
19 | if session is not None:
20 | session.__exit__(exc=exception)
21 |
22 | class Pony(object):
23 | def __init__(self, app=None):
24 | self.app = None
25 | if app is not None:
26 | self.init_app(app)
27 |
28 | def init_app(self, app):
29 | self.app = app
30 | self.app.before_request(_enter_session)
31 | self.app.teardown_request(_exit_session)
--------------------------------------------------------------------------------
/pony/flask/example/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/flask/example/__init__.py
--------------------------------------------------------------------------------
/pony/flask/example/__main__.py:
--------------------------------------------------------------------------------
1 | from .views import *
2 | from .app import app
3 |
4 | if __name__ == '__main__':
5 | db.bind(**app.config['PONY'])
6 | db.generate_mapping(create_tables=True)
7 | app.run()
--------------------------------------------------------------------------------
/pony/flask/example/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask
2 | from flask_login import LoginManager
3 | from pony.flask import Pony
4 | from .config import config
5 | from .models import db
6 |
7 | app = Flask(__name__)
8 | app.config.update(config)
9 |
10 | Pony(app)
11 | login_manager = LoginManager(app)
12 | login_manager.login_view = 'login'
13 |
14 | @login_manager.user_loader
15 | def load_user(user_id):
16 | return db.User.get(id=user_id)
17 |
--------------------------------------------------------------------------------
/pony/flask/example/config.py:
--------------------------------------------------------------------------------
1 | config = dict(
2 | DEBUG = False,
3 | SECRET_KEY = 'secret_xxx',
4 | PONY = {
5 | 'provider': 'sqlite',
6 | 'filename': 'db.db3',
7 | 'create_db': True
8 | }
9 | )
--------------------------------------------------------------------------------
/pony/flask/example/models.py:
--------------------------------------------------------------------------------
1 | from pony.orm import Database, Required, Optional
2 | from flask_login import UserMixin
3 | from datetime import datetime
4 |
5 | db = Database()
6 |
7 | class User(db.Entity, UserMixin):
8 | login = Required(str, unique=True)
9 | password = Required(str)
10 | last_login = Optional(datetime)
--------------------------------------------------------------------------------
/pony/flask/example/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello!
4 |
5 |
6 |
7 |
8 |
9 | {% with messages = get_flashed_messages() %}
10 | {% if messages %}
11 | {% for message in messages %}
12 |
{{ message }}
13 | {% endfor %}
14 | {% endif %}
15 | {% endwith %}
16 | {% if not current_user.is_authenticated %}
17 |
18 | {% else %}
19 |
Hi, {{ current_user.login }}. Your last login: {{ current_user.last_login.strftime('%Y-%m-%d') }}
20 |
Logout
21 |
List of users
22 |
23 | {% for user in users %}
24 |
25 | {% if user == current_user %}
26 | {{ user.login }}
27 | {% else %}
28 | {{ user.login }}
29 | {% endif %}
30 |
31 | {% endfor %}
32 |
33 | {% endif %}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/pony/flask/example/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Login page
4 |
5 |
6 |
7 |
8 |
9 | {% with messages = get_flashed_messages() %}
10 | {% if messages %}
11 | {% for message in messages %}
12 |
{{ message }}
13 | {% endfor %}
14 | {% endif %}
15 | {% endwith %}
16 |
Please login
17 |
18 |
25 | {% if error %}
26 |
Error: {{ error }}
27 | {% endif %}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/pony/flask/example/templates/reg.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Login page
4 |
5 |
6 |
7 |
8 |
9 | {% with messages = get_flashed_messages() %}
10 | {% if messages %}
11 | {% for message in messages %}
12 |
{{ message }}
13 | {% endfor %}
14 | {% endif %}
15 | {% endwith %}
16 |
Register
17 |
18 |
25 | {% if error %}
26 |
Error: {{ error }}
27 | {% endif %}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/pony/flask/example/views.py:
--------------------------------------------------------------------------------
1 | from .app import app
2 | from .models import db
3 | from flask import render_template, request, flash, redirect, abort
4 | from flask_login import current_user, logout_user, login_user, login_required
5 | from datetime import datetime
6 | from pony.orm import flush
7 |
8 | @app.route('/')
9 | def index():
10 | users = db.User.select()
11 | return render_template('index.html', user=current_user, users=users)
12 |
13 | @app.route('/login', methods=['GET', 'POST'])
14 | def login():
15 | if request.method == 'POST':
16 | username = request.form['username']
17 | password = request.form['password']
18 | possible_user = db.User.get(login=username)
19 | if not possible_user:
20 | flash('Wrong username')
21 | return redirect('/login')
22 | if possible_user.password == password:
23 | possible_user.last_login = datetime.now()
24 | login_user(possible_user)
25 | return redirect('/')
26 |
27 | flash('Wrong password')
28 | return redirect('/login')
29 | else:
30 | return render_template('login.html')
31 |
32 | @app.route('/reg', methods=['GET', 'POST'])
33 | def reg():
34 | if request.method == 'POST':
35 | username = request.form['username']
36 | password = request.form['password']
37 | exist = db.User.get(login=username)
38 | if exist:
39 | flash('Username %s is already taken, choose another one' % username)
40 | return redirect('/reg')
41 |
42 | user = db.User(login=username, password=password)
43 | user.last_login = datetime.now()
44 | flush()
45 | login_user(user)
46 | flash('Successfully registered')
47 | return redirect('/')
48 | else:
49 | return render_template('reg.html')
50 |
51 | @app.route('/logout')
52 | @login_required
53 | def logout():
54 | logout_user()
55 | flash('Logged out')
56 | return redirect('/')
--------------------------------------------------------------------------------
/pony/options.py:
--------------------------------------------------------------------------------
1 | DEBUG = True
2 |
3 | STATIC_DIR = None
4 |
5 | CUT_TRACEBACK = True
6 |
7 | #postprocessing options:
8 | STD_DOCTYPE = ''
9 | STD_STYLESHEETS = [
10 | ("/pony/static/blueprint/screen.css", "screen, projection"),
11 | ("/pony/static/blueprint/print.css", "print"),
12 | ("/pony/static/blueprint/ie.css.css", "screen, projection", "if IE"),
13 | ("/pony/static/css/default.css", "screen, projection"),
14 | ]
15 | BASE_STYLESHEETS_PLACEHOLDER = ''
16 | COMPONENT_STYLESHEETS_PLACEHOLDER = ''
17 | SCRIPTS_PLACEHOLDER = ''
18 |
19 | # reloading options:
20 | RELOADING_CHECK_INTERVAL = 1.0 # in seconds
21 |
22 | # logging options:
23 | LOG_TO_SQLITE = None
24 | LOGGING_LEVEL = None
25 | LOGGING_PONY_LEVEL = None
26 |
27 | #auth options:
28 | MAX_SESSION_CTIME = 60*24 # one day
29 | MAX_SESSION_MTIME = 60*2 # 2 hours
30 | MAX_LONGLIFE_SESSION = 14 # 14 days
31 | COOKIE_SERIALIZATION_TYPE = 'json' # may be 'json' or 'pickle'
32 | COOKIE_NAME = 'pony'
33 | COOKIE_PATH = '/'
34 | COOKIE_DOMAIN = None
35 | HASH_ALGORITHM = None # sha-1 by default
36 | # HASH_ALGORITHM = hashlib.sha512
37 |
38 | SESSION_STORAGE = None # pony.sessionstorage.memcachedstorage by default
39 | # SESSION_STORAGE = mystoragemodule
40 | # SESSION_STORAGE = False # means use cookies for save session data,
41 | # can lead to race conditions
42 |
43 | # memcached options (ignored under GAE):
44 | MEMCACHE = None # Use in-process python version by default
45 | # MEMCACHE = [ "127.0.0.1:11211" ]
46 | # MEMCACHE = MyMemcacheConnectionImplementation(...)
47 | ALTERNATIVE_SESSION_MEMCACHE = None # Use general memcache connection by default
48 | ALTERNATIVE_ORM_MEMCACHE = None # Use general memcache connection by default
49 | ALTERNATIVE_TEMPLATING_MEMCACHE = None # Use general memcache connection by default
50 | ALTERNATIVE_RESPONSE_MEMCACHE = None # Use general memcache connection by default
51 |
52 | # pickle options:
53 | PICKLE_START_OFFSET = 230
54 | PICKLE_HTML_AS_PLAIN_STR = True
55 |
56 | # encoding options for pony.pathces.repr
57 | RESTORE_ESCAPES = True
58 | SOURCE_ENCODING = None
59 | CONSOLE_ENCODING = None
60 |
61 | # db options
62 | MAX_FETCH_COUNT = None
63 |
64 | # used for select(...).show()
65 | CONSOLE_WIDTH = 80
66 |
67 | # sql translator options
68 | SIMPLE_ALIASES = True # if True just use entity name like "Course-1"
69 | # if False use attribute names chain as an alias like "student-grades-course"
70 |
71 | INNER_JOIN_SYNTAX = False # put conditions to INNER JOIN ... ON ... or to WHERE ...
72 |
73 | # debugging options
74 | DEBUGGING_REMOVE_ADDR = True
75 | DEBUGGING_RESTORE_ESCAPES = True
76 |
--------------------------------------------------------------------------------
/pony/orm/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | from pony.orm.core import *
4 |
--------------------------------------------------------------------------------
/pony/orm/dbproviders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/orm/dbproviders/__init__.py
--------------------------------------------------------------------------------
/pony/orm/dbproviders/cockroach.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from pony.py23compat import buffer, int_types
3 |
4 | from decimal import Decimal
5 | from datetime import datetime, date, time, timedelta
6 | from uuid import UUID
7 |
8 | try:
9 | import psycopg2
10 | except ImportError:
11 | try:
12 | from psycopg2cffi import compat
13 | except ImportError:
14 | raise ImportError('In order to use PonyORM with CockroachDB please install psycopg2 or psycopg2cffi')
15 | else:
16 | compat.register()
17 |
18 | from pony.orm.dbproviders.postgres import (
19 | PGSQLBuilder, PGColumn, PGSchema, PGTranslator, PGProvider,
20 | PGIntConverter, PGRealConverter,
21 | PGDatetimeConverter, PGTimedeltaConverter,
22 | PGBlobConverter, PGJsonConverter, PGArrayConverter,
23 | )
24 |
25 | from pony.orm import core, dbapiprovider, ormtypes
26 | from pony.orm.core import log_orm
27 | from pony.orm.dbapiprovider import wrap_dbapi_exceptions
28 |
29 | NoneType = type(None)
30 |
31 | class CRColumn(PGColumn):
32 | auto_template = 'SERIAL PRIMARY KEY'
33 |
34 | class CRSchema(PGSchema):
35 | column_class = CRColumn
36 |
37 | class CRTranslator(PGTranslator):
38 | pass
39 |
40 | class CRSQLBuilder(PGSQLBuilder):
41 | pass
42 |
43 | class CRIntConverter(PGIntConverter):
44 | signed_types = {None: 'INT', 8: 'INT2', 16: 'INT2', 24: 'INT8', 32: 'INT8', 64: 'INT8'}
45 | unsigned_types = {None: 'INT', 8: 'INT2', 16: 'INT4', 24: 'INT8', 32: 'INT8'}
46 | # signed_types = {None: 'INT', 8: 'INT2', 16: 'INT2', 24: 'INT4', 32: 'INT4', 64: 'INT8'}
47 | # unsigned_types = {None: 'INT', 8: 'INT2', 16: 'INT4', 24: 'INT4', 32: 'INT8'}
48 |
49 | class CRBlobConverter(PGBlobConverter):
50 | def sql_type(converter):
51 | return 'BYTES'
52 |
53 | class CRTimedeltaConverter(PGTimedeltaConverter):
54 | sql_type_name = 'INTERVAL'
55 |
56 | class PGUuidConverter(dbapiprovider.UuidConverter):
57 | def py2sql(converter, val):
58 | return val
59 |
60 | class CRArrayConverter(PGArrayConverter):
61 | array_types = {
62 | int: ('INT', PGIntConverter),
63 | str: ('STRING', dbapiprovider.StrConverter),
64 | float: ('DOUBLE PRECISION', PGRealConverter)
65 | }
66 |
67 | class CRProvider(PGProvider):
68 | dbapi_module = psycopg2
69 | dbschema_cls = CRSchema
70 | translator_cls = CRTranslator
71 | sqlbuilder_cls = CRSQLBuilder
72 | array_converter_cls = CRArrayConverter
73 |
74 | default_schema_name = 'public'
75 |
76 | fk_types = { 'SERIAL' : 'INT8' }
77 |
78 | def normalize_name(provider, name):
79 | return name[:provider.max_name_len].lower()
80 |
81 | @wrap_dbapi_exceptions
82 | def set_transaction_mode(provider, connection, cache):
83 | assert not cache.in_transaction
84 | db_session = cache.db_session
85 | if db_session is not None and db_session.ddl:
86 | cache.immediate = False
87 | if cache.immediate and connection.autocommit:
88 | connection.autocommit = False
89 | if core.local.debug: log_orm('SWITCH FROM AUTOCOMMIT TO TRANSACTION MODE')
90 | elif not cache.immediate and not connection.autocommit:
91 | connection.autocommit = True
92 | if core.local.debug: log_orm('SWITCH TO AUTOCOMMIT MODE')
93 | if db_session is not None and (db_session.serializable or db_session.ddl):
94 | cache.in_transaction = True
95 |
96 | converter_classes = [
97 | (NoneType, dbapiprovider.NoneConverter),
98 | (bool, dbapiprovider.BoolConverter),
99 | (str, dbapiprovider.StrConverter),
100 | (int_types, CRIntConverter),
101 | (float, PGRealConverter),
102 | (Decimal, dbapiprovider.DecimalConverter),
103 | (datetime, PGDatetimeConverter),
104 | (date, dbapiprovider.DateConverter),
105 | (time, dbapiprovider.TimeConverter),
106 | (timedelta, CRTimedeltaConverter),
107 | (UUID, PGUuidConverter),
108 | (buffer, CRBlobConverter),
109 | (ormtypes.Json, PGJsonConverter),
110 | ]
111 |
112 | provider_cls = CRProvider
113 |
--------------------------------------------------------------------------------
/pony/orm/examples/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/orm/examples/__init__.py
--------------------------------------------------------------------------------
/pony/orm/examples/bottle_example.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | from bottle import default_app, install, route, request, redirect, run, template
4 |
5 | # Import eStore model http://editor.ponyorm.com/user/pony/eStore
6 | from pony.orm.examples.estore import *
7 | from pony.orm.integration.bottle_plugin import PonyPlugin
8 |
9 | # After the plugin is installed each request will be processed
10 | # in a separate database session. Once the HTTP request processing
11 | # is finished the plugin does the following:
12 | # * commit the changes to the database (or rollback if an exception happened)
13 | # * clear the transaction cache
14 | # * return the database connection to the connection pool
15 | install(PonyPlugin())
16 |
17 | @route('/')
18 | @route('/products/')
19 | def all_products():
20 | # Get the list of all products from the database
21 | products = select(p for p in Product)
22 | return template('''
23 | List of products
24 |
29 | ''', products=products)
30 |
31 | @route('/products/:id/')
32 | def show_product(id):
33 | # Get the instance of the Product entity by the primary key
34 | p = Product[id]
35 | # You can traverse entity relationship attributes inside the template
36 | # In this examples it is many-to-many relationship p.categories
37 | # Since the data were not loaded into the cache yet,
38 | # it will result in a separate SQL query.
39 | return template('''
40 | {{ p.name }}
41 | Price: {{ p.price }}
42 | Product categories:
43 |
44 | %for c in p.categories:
45 | {{ c.name }}
46 | %end
47 |
48 | Edit product info
49 | Return to all products
50 | ''', p=p)
51 |
52 | @route('/products/:id/edit/')
53 | def edit_product(id):
54 | # Get the instance of the Product entity and display its attributes
55 | p = Product[id]
56 | return template('''
57 |
70 | Discard changes
71 |
Return to all products
72 | ''', p=p)
73 |
74 | @route('/products/:id/edit/', method='POST')
75 | def save_product(id):
76 | # Get the instance of the Product entity
77 | p = Product[id]
78 | # Update the attributes with the new values
79 | p.name = request.forms.get('name')
80 | p.price = request.forms.get('price')
81 | # We might put the commit() command here, but it is not necessary
82 | # because PonyPlugin will take care of this.
83 | redirect("/products/%d/" % p.id)
84 | # The Bottle's redirect function raises the HTTPResponse exception.
85 | # Normally PonyPlugin closes the session with rollback
86 | # if a callback function raises an exception. But in this case
87 | # PonyPlugin understands that this exception is not the error
88 | # and closes the session with commit.
89 |
90 |
91 | run(debug=True, host='localhost', port=8080, reloader=True)
92 |
--------------------------------------------------------------------------------
/pony/orm/examples/compositekeys.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 |
3 | from datetime import date
4 | from pony.orm.core import *
5 |
6 | db = Database('sqlite', 'complex.sqlite', create_db=True)
7 |
8 | class Group(db.Entity):
9 | dept = Required('Department')
10 | year = Required(int)
11 | spec = Required(int)
12 | students = Set('Student')
13 | courses = Set('Course')
14 | lessons = Set('Lesson', columns=['building', 'number', 'dt'])
15 | PrimaryKey(dept, year, spec)
16 |
17 | class Department(db.Entity):
18 | number = PrimaryKey(int)
19 | faculty = Required('Faculty')
20 | name = Required(str)
21 | groups = Set(Group)
22 | teachers = Set('Teacher')
23 |
24 | class Faculty(db.Entity):
25 | number = PrimaryKey(int)
26 | name = Required(str)
27 | depts = Set(Department)
28 |
29 | class Student(db.Entity):
30 | name = Required(str)
31 | group = Required(Group)
32 | dob = Optional(date)
33 | grades = Set('Grade')
34 | PrimaryKey(name, group)
35 |
36 | class Grade(db.Entity):
37 | student = Required(Student, columns=['student_name', 'dept', 'year', 'spec'])
38 | task = Required('Task')
39 | date = Required(date)
40 | value = Required(int)
41 | PrimaryKey(student, task)
42 |
43 | class Task(db.Entity):
44 | course = Required('Course')
45 | type = Required(str)
46 | number = Required(int)
47 | descr = Optional(str)
48 | grades = Set(Grade)
49 | PrimaryKey(course, type, number)
50 |
51 | class Course(db.Entity):
52 | subject = Required('Subject')
53 | semester = Required(int)
54 | groups = Set(Group)
55 | tasks = Set(Task)
56 | lessons = Set('Lesson')
57 | teachers = Set('Teacher')
58 | PrimaryKey(subject, semester)
59 |
60 | class Subject(db.Entity):
61 | name = PrimaryKey(str)
62 | descr = Optional(str)
63 | courses = Set(Course)
64 |
65 | class Room(db.Entity):
66 | building = Required(str)
67 | number = Required(str)
68 | floor = Optional(int)
69 | schedules = Set('Lesson')
70 | PrimaryKey(building, number)
71 |
72 | class Teacher(db.Entity):
73 | dept = Required(Department)
74 | name = Required(str)
75 | courses = Set(Course)
76 | lessons = Set('Lesson')
77 |
78 | class Lesson(db.Entity):
79 | _table_ = 'Schedule'
80 | groups = Set(Group)
81 | course = Required(Course)
82 | room = Required(Room)
83 | teacher = Required(Teacher)
84 | date = Required(date)
85 | PrimaryKey(room, date)
86 | composite_key(teacher, date)
87 |
88 | db.generate_mapping(create_tables=True)
89 |
90 | def test_queries():
91 | select(grade for grade in Grade if grade.task.type == 'Lab')[:]
92 | select(grade for grade in Grade if grade.task.descr.startswith('Intermediate'))[:]
93 | select(grade for grade in Grade if grade.task.course.semester == 2)[:]
94 | select(grade for grade in Grade if grade.task.course.subject.name == 'Math')[:]
95 | select(grade for grade in Grade if 'elementary' in grade.task.course.subject.descr.lower())[:]
96 | select(grade for grade in Grade if 'elementary' in grade.task.course.subject.descr.lower() and grade.task.descr.startswith('Intermediate'))[:]
97 | select(grade for grade in Grade if grade.task.descr.startswith('Intermediate') and 'elementary' in grade.task.course.subject.descr.lower())[:]
98 | select(s for s in Student if s.group.dept.faculty.name == 'Abc')[:]
99 | select(g for g in Group if avg(g.students.grades.value) > 4)[:]
100 | select(g for g in Group if avg(g.students.grades.value) > 4 and max(g.students.grades.date) < date(2011, 3, 2))[:]
101 | select(g for g in Group if '4-A' in g.lessons.room.number)[:]
102 | select(g for g in Group if 1 in g.lessons.room.floor)[:]
103 | select(t for t in Teacher if t not in t.courses.groups.lessons.teacher)[:]
104 |
105 | sql_debug(True)
106 |
--------------------------------------------------------------------------------
/pony/orm/examples/demo.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | from decimal import Decimal
4 | from pony.orm import *
5 |
6 | db = Database("sqlite", "demo.sqlite", create_db=True)
7 |
8 | class Customer(db.Entity):
9 | id = PrimaryKey(int, auto=True)
10 | name = Required(str)
11 | email = Required(str, unique=True)
12 | orders = Set("Order")
13 |
14 | class Order(db.Entity):
15 | id = PrimaryKey(int, auto=True)
16 | total_price = Required(Decimal)
17 | customer = Required(Customer)
18 | items = Set("OrderItem")
19 |
20 | class Product(db.Entity):
21 | id = PrimaryKey(int, auto=True)
22 | name = Required(str)
23 | price = Required(Decimal)
24 | items = Set("OrderItem")
25 |
26 | class OrderItem(db.Entity):
27 | quantity = Required(int, default=1)
28 | order = Required(Order)
29 | product = Required(Product)
30 | PrimaryKey(order, product)
31 |
32 | sql_debug(True)
33 | db.generate_mapping(create_tables=True)
34 |
35 | def populate_database():
36 | c1 = Customer(name='John Smith', email='john@example.com')
37 | c2 = Customer(name='Matthew Reed', email='matthew@example.com')
38 | c3 = Customer(name='Chuan Qin', email='chuanqin@example.com')
39 | c4 = Customer(name='Rebecca Lawson', email='rebecca@example.com')
40 | c5 = Customer(name='Oliver Blakey', email='oliver@example.com')
41 |
42 | p1 = Product(name='Kindle Fire HD', price=Decimal('284.00'))
43 | p2 = Product(name='Apple iPad with Retina Display', price=Decimal('478.50'))
44 | p3 = Product(name='SanDisk Cruzer 16 GB USB Flash Drive', price=Decimal('9.99'))
45 | p4 = Product(name='Kingston DataTraveler 16GB USB 2.0', price=Decimal('9.98'))
46 | p5 = Product(name='Samsung 840 Series 120GB SATA III SSD', price=Decimal('98.95'))
47 | p6 = Product(name='Crucial m4 256GB SSD SATA 6Gb/s', price=Decimal('188.67'))
48 |
49 | o1 = Order(customer=c1, total_price=Decimal('292.00'))
50 | OrderItem(order=o1, product=p1)
51 | OrderItem(order=o1, product=p4, quantity=2)
52 |
53 | o2 = Order(customer=c1, total_price=Decimal('478.50'))
54 | OrderItem(order=o2, product=p2)
55 |
56 | o3 = Order(customer=c2, total_price=Decimal('680.50'))
57 | OrderItem(order=o3, product=p2)
58 | OrderItem(order=o3, product=p4, quantity=2)
59 | OrderItem(order=o3, product=p6)
60 |
61 | o4 = Order(customer=c3, total_price=Decimal('99.80'))
62 | OrderItem(order=o4, product=p4, quantity=10)
63 |
64 | o5 = Order(customer=c4, total_price=Decimal('722.00'))
65 | OrderItem(order=o5, product=p1)
66 | OrderItem(order=o5, product=p2)
67 |
68 | commit()
69 |
70 |
--------------------------------------------------------------------------------
/pony/orm/examples/inheritance1.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | from decimal import Decimal
4 | from datetime import date
5 |
6 | from pony import options
7 | options.CUT_TRACEBACK = False
8 |
9 | from pony.orm.core import *
10 |
11 | sql_debug(False)
12 |
13 | db = Database('sqlite', 'inheritance1.sqlite', create_db=True)
14 |
15 | class Person(db.Entity):
16 | id = PrimaryKey(int, auto=True)
17 | name = Required(str)
18 | dob = Optional(date)
19 | ssn = Required(str, unique=True)
20 |
21 | class Student(Person):
22 | group = Required("Group")
23 | mentor = Optional("Teacher")
24 | attend_courses = Set("Course")
25 |
26 | class Teacher(Person):
27 | teach_courses = Set("Course")
28 | apprentices = Set("Student")
29 | salary = Required(Decimal)
30 |
31 | class Assistant(Student, Teacher):
32 | pass
33 |
34 | class Professor(Teacher):
35 | position = Required(str)
36 |
37 | class Group(db.Entity):
38 | number = PrimaryKey(int)
39 | students = Set("Student")
40 |
41 | class Course(db.Entity):
42 | name = Required(str)
43 | semester = Required(int)
44 | students = Set(Student)
45 | teachers = Set(Teacher)
46 | PrimaryKey(name, semester)
47 |
48 | db.generate_mapping(create_tables=True)
49 |
50 | @db_session
51 | def populate_database():
52 | if Person.select().first():
53 | return # already populated
54 |
55 | p = Person(name='Person1', ssn='SSN1')
56 | g = Group(number=123)
57 | prof = Professor(name='Professor1', salary=1000, position='position1', ssn='SSN5')
58 | a1 = Assistant(name='Assistant1', group=g, salary=100, ssn='SSN4', mentor=prof)
59 | a2 = Assistant(name='Assistant2', group=g, salary=200, ssn='SSN6', mentor=prof)
60 | s1 = Student(name='Student1', group=g, ssn='SSN2', mentor=a1)
61 | s2 = Student(name='Student2', group=g, ssn='SSN3')
62 | commit()
63 |
64 | def show_all_persons():
65 | for obj in Person.select():
66 | print(obj)
67 | for attr in obj._attrs_:
68 | print(attr.name, "=", attr.__get__(obj))
69 | print()
70 |
71 | if __name__ == '__main__':
72 | populate_database()
73 | # show_all_persons()
74 |
75 | sql_debug(True)
76 |
77 | with db_session:
78 | s1 = Student.get(name='Student1')
79 | if s1 is None:
80 | print('Student1 not found')
81 | else:
82 | mentor = s1.mentor
83 | print(mentor.name, 'is mentor of Student1')
84 | print('Is he assistant?', isinstance(mentor, Assistant))
85 | print()
86 |
87 | for s in Student.select(lambda s: s.mentor.salary == 1000):
88 | print(s.name)
89 |
--------------------------------------------------------------------------------
/pony/orm/examples/numbers.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | from pony.orm.core import *
4 |
5 | db = Database()
6 |
7 | class Numbers(db.Entity):
8 | _table_ = "Numbers"
9 | id = PrimaryKey(int, auto=True)
10 | int8 = Required(int, size=8) # TINYINT
11 | int16 = Required(int, size=16) # SMALLINT
12 | int24 = Required(int, size=24) # MEDIUMINT
13 | int32 = Required(int, size=32) # INTEGER
14 | int64 = Required(int, size=64) # BIGINT
15 | uint8 = Required(int, size=8, unsigned=True) # TINYINT UNSIGNED
16 | uint16 = Required(int, size=16, unsigned=True) # SMALLINT UNSIGNED
17 | uint24 = Required(int, size=24, unsigned=True) # MEDIUMINT UNSIGNED
18 | uint32 = Required(int, size=32, unsigned=True) # INTEGER UNSIGNED
19 | # uint64 = Required(int, size=64, unsigned=True) # BIGINT UNSIGNED, supported by MySQL and Oracle
20 |
21 | sql_debug(True) # Output all SQL queries to stdout
22 |
23 | db.bind('sqlite', 'test_numbers.sqlite', create_db=True)
24 | #db.bind('mysql', host="localhost", user="pony", passwd="pony", db="test_numbers")
25 | #db.bind('postgres', user='pony', password='pony', host='localhost', database='test_numbers')
26 | #db.bind('oracle', 'test_numbers/pony@localhost')
27 |
28 | db.drop_table("Numbers", if_exists=True, with_all_data=True)
29 | db.generate_mapping(create_tables=True)
30 |
31 | @db_session
32 | def populate_database():
33 | lo = Numbers(int8=-128,
34 | int16=-32768,
35 | int24=-8388608,
36 | int32=-2147483648,
37 | int64=-9223372036854775808,
38 | uint8=0, uint16=0, uint24=0, uint32=0) #, uint64=0)
39 | hi = Numbers(int8=127,
40 | int16=32767,
41 | int24=8388607,
42 | int32=2147483647,
43 | int64=9223372036854775807,
44 | uint8=255,
45 | uint16=65535,
46 | uint24=16777215,
47 | uint32=4294967295)
48 | # uint64=18446744073709551615)
49 | commit()
50 |
51 | @db_session
52 | def test_data():
53 | for n in Numbers.select():
54 | print(n.id, n.int8, n.int16, n.int24, n.int32, n.int64,
55 | n.uint8, n.uint16, n.uint24, n.uint32) #, n.uint64)
56 |
57 | if __name__ == '__main__':
58 | populate_database()
59 | test_data()
60 |
--------------------------------------------------------------------------------
/pony/orm/examples/university2.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function
2 |
3 | from pony.orm.core import *
4 | from decimal import Decimal
5 | from datetime import date
6 |
7 | db = Database()
8 |
9 | class Faculty(db.Entity):
10 | _table_ = 'Faculties'
11 | number = PrimaryKey(int)
12 | name = Required(str, unique=True)
13 | departments = Set('Department')
14 |
15 | class Department(db.Entity):
16 | _table_ = 'Departments'
17 | number = PrimaryKey(int)
18 | name = Required(str, unique=True)
19 | faculty = Required(Faculty)
20 | teachers = Set('Teacher')
21 | majors = Set('Major')
22 | groups = Set('Group')
23 |
24 | class Group(db.Entity):
25 | _table_ = 'Groups'
26 | number = PrimaryKey(int)
27 | grad_year = Required(int)
28 | department = Required(Department, column='dep')
29 | lessons = Set('Lesson', columns=['day_of_week', 'meeting_time', 'classroom_number', 'building'])
30 | students = Set('Student')
31 |
32 | class Student(db.Entity):
33 | _table_ = 'Students'
34 | name = Required(str)
35 | scholarship = Required(Decimal, 10, 2, default=Decimal('0.0'))
36 | group = Required(Group)
37 | grades = Set('Grade')
38 |
39 | class Major(db.Entity):
40 | _table_ = 'Majors'
41 | name = PrimaryKey(str)
42 | department = Required(Department)
43 | courses = Set('Course')
44 |
45 | class Subject(db.Entity):
46 | _table_ = 'Subjects'
47 | name = PrimaryKey(str)
48 | courses = Set('Course')
49 | teachers = Set('Teacher')
50 |
51 | class Course(db.Entity):
52 | _table_ = 'Courses'
53 | major = Required(Major)
54 | subject = Required(Subject)
55 | semester = Required(int)
56 | composite_key(major, subject, semester)
57 | lect_hours = Required(int)
58 | pract_hours = Required(int)
59 | credit = Required(int)
60 | lessons = Set('Lesson')
61 | grades = Set('Grade')
62 |
63 | class Lesson(db.Entity):
64 | _table_ = 'Lessons'
65 | day_of_week = Required(int)
66 | meeting_time = Required(int)
67 | classroom = Required('Classroom')
68 | PrimaryKey(day_of_week, meeting_time, classroom)
69 | course = Required(Course)
70 | teacher = Required('Teacher')
71 | groups = Set(Group)
72 |
73 | class Grade(db.Entity):
74 | _table_ = 'Grades'
75 | student = Required(Student)
76 | course = Required(Course)
77 | PrimaryKey(student, course)
78 | teacher = Required('Teacher')
79 | date = Required(date)
80 | value = Required(str)
81 |
82 | class Teacher(db.Entity):
83 | _table_ = 'Teachers'
84 | name = Required(str)
85 | degree = Optional(str)
86 | department = Required(Department)
87 | subjects = Set(Subject)
88 | lessons = Set(Lesson)
89 | grades = Set(Grade)
90 |
91 | class Building(db.Entity):
92 | _table_ = 'Buildings'
93 | number = PrimaryKey(str)
94 | description = Optional(str)
95 | classrooms = Set('Classroom')
96 |
97 | class Classroom(db.Entity):
98 | _table_ = 'Classrooms'
99 | building = Required(Building)
100 | number = Required(str)
101 | PrimaryKey(building, number)
102 | description = Optional(str)
103 | lessons = Set(Lesson)
104 |
105 | db.bind('sqlite', 'university2.sqlite', create_db=True)
106 | #db.bind('mysql', host='localhost', user='pony', passwd='pony', db='university2')
107 | #db.bind('postgres', user='pony', password='pony', host='localhost', database='university2')
108 | #db.bind('oracle', 'university2/pony@localhost')
109 |
110 | db.generate_mapping(create_tables=True)
111 |
112 | sql_debug(True)
113 |
114 | def test_queries():
115 | # very simple query
116 | select(s for s in Student)[:]
117 |
118 | # one condition
119 | select(s for s in Student if s.scholarship > 0)[:]
120 |
121 | # multiple conditions
122 | select(s for s in Student if s.scholarship > 0 and s.group.number == 4142)[:]
123 |
124 | # no join here - attribute can be found in table Students
125 | select(s for s in Student if s.group.number == 4142)[:]
126 |
127 | # automatic join of two tables because grad_year is stored in table Groups
128 | select(s for s in Student if s.group.grad_year == 2011)[:]
129 |
130 | # still two tables are joined
131 | select(s for s in Student if s.group.department.number == 44)[:]
132 |
133 | # automatic join of tree tables
134 | select(s for s in Student if s.group.department.name == 'Ancient Philosophy')[:]
135 |
136 | # manual join of tables will produce equivalent query
137 | select(s for s in Student for g in Group if s.group == g and g.department.name == 'Ancient Philosophy')[:]
138 |
139 | # join two tables by composite foreign key
140 | select(c for c in Classroom for l in Lesson if l.classroom == c and l.course.subject.name == 'Physics')[:]
141 |
142 | # Lessons will be joined with Buildings directly without Classrooms
143 | select(s for s in Subject for l in Lesson if s == l.course.subject and l.classroom.building.description == 'some description')[:]
144 |
145 | # just another example of join of many tables
146 | select(c for c in Course if c.major.department.faculty.number == 4)[:]
147 |
--------------------------------------------------------------------------------
/pony/orm/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/orm/integration/__init__.py
--------------------------------------------------------------------------------
/pony/orm/integration/bottle_plugin.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | from bottle import HTTPResponse, HTTPError
4 | from pony.orm.core import db_session
5 |
6 | def is_allowed_exception(e):
7 | return isinstance(e, HTTPResponse) and not isinstance(e, HTTPError)
8 |
9 | class PonyPlugin(object):
10 | name = 'pony'
11 | api = 2
12 | def apply(self, callback, route):
13 | return db_session(allowed_exceptions=is_allowed_exception)(callback)
14 |
--------------------------------------------------------------------------------
/pony/orm/serialization.py:
--------------------------------------------------------------------------------
1 | import json
2 | from datetime import date, datetime
3 | from decimal import Decimal
4 | from collections import defaultdict
5 |
6 | from pony.orm.core import Entity, TransactionError
7 | from pony.utils import cut_traceback, throw
8 |
9 | class Bag(object):
10 | def __init__(bag, database):
11 | bag.database = database
12 | bag.session_cache = None
13 | bag.entity_configs = {}
14 | bag.objects = defaultdict(set)
15 | bag.vars = {}
16 | bag.dicts = defaultdict(dict)
17 | @cut_traceback
18 | def config(bag, entity, only=None, exclude=None, with_collections=True, with_lazy=False, related_objects=True):
19 | if bag.database.entities.get(entity.__name__) is not entity: throw(TypeError,
20 | 'Entity %s does not belong to database %r' % (entity.__name__, bag.database))
21 | attrs = entity._get_attrs_(only, exclude, with_collections, with_lazy)
22 | bag.entity_configs[entity] = attrs, related_objects
23 | return attrs, related_objects
24 | @cut_traceback
25 | def put(bag, x):
26 | if isinstance(x, Entity):
27 | bag._put_object(x)
28 | else:
29 | try: x = list(x)
30 | except: throw(TypeError, 'Entity instance or a sequence of instances expected. Got: %r' % x)
31 | for item in x:
32 | if not isinstance(item, Entity): throw(TypeError,
33 | 'Entity instance or a sequence of instances expected. Got: %r' % item)
34 | bag._put_object(item)
35 | def _put_object(bag, obj):
36 | entity = obj.__class__
37 | if bag.database.entities.get(entity.__name__) is not entity: throw(TypeError,
38 | 'Entity %s does not belong to database %r' % (entity.__name__, bag.database))
39 | cache = bag.session_cache
40 | if cache is None: cache = bag.session_cache = obj._session_cache_
41 | elif obj._session_cache_ is not cache: throw(TransactionError,
42 | 'An attempt to mix objects belonging to different transactions')
43 | bag.objects[entity].add(obj)
44 | def _reduce_composite_pk(bag, pk):
45 | return ','.join(str(item).replace('*', '**').replace(',', '*,') for item in pk)
46 | @cut_traceback
47 | def to_dict(bag):
48 | bag.dicts.clear()
49 | for entity, objects in bag.objects.items():
50 | for obj in objects:
51 | dicts = bag.dicts[entity]
52 | if obj not in dicts: bag._process_object(obj)
53 | result = defaultdict(dict)
54 | for entity, dicts in bag.dicts.items():
55 | composite_pk = len(entity._pk_columns_) > 1
56 | for obj, d in dicts.items():
57 | pk = obj._get_raw_pkval_()
58 | if composite_pk: pk = bag._reduce_composite_pk(pk)
59 | else: pk = pk[0]
60 | result[entity.__name__][pk] = d
61 | bag.dicts.clear()
62 | return result
63 | def _process_object(bag, obj, process_related=True):
64 | entity = obj.__class__
65 | try: attrs, related_objects = bag.entity_configs[entity]
66 | except KeyError: attrs, related_objects = bag.config(entity)
67 | process_related_objects = process_related and related_objects
68 | d = {}
69 | for attr in attrs:
70 | value = attr.__get__(obj)
71 | if attr.is_collection:
72 | if not process_related:
73 | continue
74 | if process_related_objects:
75 | for related_obj in value:
76 | if related_obj not in bag.dicts:
77 | bag._process_object(related_obj, process_related=False)
78 | if attr.reverse.entity._pk_is_composite_:
79 | value = sorted(bag._reduce_composite_pk(item._get_raw_pkval_()) for item in value)
80 | else: value = sorted(item._get_raw_pkval_()[0] for item in value)
81 | elif attr.is_relation:
82 | if value is not None:
83 | if process_related_objects:
84 | bag._process_object(value, process_related=False)
85 | value = value._get_raw_pkval_()
86 | if len(value) == 1: value = value[0]
87 | d[attr.name] = value
88 | bag.dicts[entity][obj] = d
89 | @cut_traceback
90 | def to_json(bag):
91 | return json.dumps(bag.to_dict(), default=json_converter, indent=2, sort_keys=True)
92 |
93 | def to_dict(objects):
94 | if isinstance(objects, Entity): objects = [ objects ]
95 | objects = iter(objects)
96 | try: first_object = next(objects)
97 | except StopIteration: return {}
98 | if not isinstance(first_object, Entity): throw(TypeError,
99 | 'Entity instance or a sequence of instances expected. Got: %r' % first_object)
100 | database = first_object._database_
101 | bag = Bag(database)
102 | bag.put(first_object)
103 | bag.put(objects)
104 | return dict(bag.to_dict())
105 |
106 | def to_json(objects):
107 | return json.dumps(to_dict(objects), default=json_converter, indent=2, sort_keys=True)
108 |
109 | def json_converter(x):
110 | if isinstance(x, (datetime, date, Decimal)):
111 | return str(x)
112 | raise TypeError(x)
113 |
--------------------------------------------------------------------------------
/pony/orm/sqlsymbols.py:
--------------------------------------------------------------------------------
1 | symbols = [ 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'SELECT_FOR_UPDATE',
2 | 'FROM', 'INNER_JOIN', 'LEFT_JOIN', 'WHERE', 'GROUP_BY', 'HAVING',
3 | 'UNION', 'INTERSECT', 'EXCEPT',
4 | 'ORDER_BY', 'LIMIT', 'ASC', 'DESC',
5 | 'DISTINCT', 'ALL', 'AGGREGATES', 'AS',
6 | 'COUNT', 'SUM', 'MIN', 'MAX', 'AVG',
7 | 'TABLE', 'COLUMN', 'PARAM', 'VALUE', 'AND', 'OR', 'NOT',
8 | 'EQ', 'NE', 'LT', 'LE', 'GT', 'GE', 'IS_NULL', 'IS_NOT_NULL',
9 | 'LIKE', 'NOT_LIKE', 'BETWEEN', 'NOT_BETWEEN',
10 | 'IN', 'NOT_IN', 'EXISTS', 'NOT_EXISTS', 'ROW',
11 | 'ADD', 'SUB', 'MUL', 'DIV', 'POW', 'NEG', 'ABS',
12 | 'UPPER', 'LOWER', 'CONCAT', 'STRIN', 'LIKE', 'SUBSTR', 'LENGTH',
13 | 'TRIM', 'LTRIM', 'RTRIM', 'REPLACE',
14 | 'CASE', 'COALESCE',
15 | 'TO_INT', 'RANDOM',
16 | 'DATE', 'YEAR', 'MONTH', 'DAY', 'HOUR', 'MINUTE', 'SECOND', 'TODAY', 'NOW',
17 | 'DATE_ADD', 'DATE_SUB', 'DATETIME_ADD', 'DATETIME_SUB' ]
18 |
19 | globals().update((s, s) for s in symbols)
20 |
--------------------------------------------------------------------------------
/pony/orm/tests/__init__.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import os
3 | import types
4 | import pony.orm.core, pony.options
5 |
6 | pony.options.CUT_TRACEBACK = False
7 | pony.orm.core.sql_debug(False)
8 |
9 |
10 | def _load_env():
11 | settings_filename = os.environ.get('pony_test_db')
12 | if settings_filename is None:
13 | print('use default sqlite provider')
14 | return dict(provider='sqlite', filename=':memory:')
15 | with open(settings_filename, 'r') as f:
16 | content = f.read()
17 |
18 | config = {}
19 | exec(content, config)
20 | settings = config.get('settings')
21 | if settings is None or not isinstance(settings, dict):
22 | raise ValueError('Incorrect settings pony test db file contents')
23 | provider = settings.get('provider')
24 | if provider is None:
25 | raise ValueError('Incorrect settings pony test db file contents: provider was not specified')
26 | print('use provider %s' % provider)
27 | return settings
28 |
29 |
30 | db_params = _load_env()
31 |
32 |
33 | def setup_database(db):
34 | if db.provider is None:
35 | db.bind(**db_params)
36 | if db.schema is None:
37 | db.generate_mapping(check_tables=False)
38 | db.drop_all_tables(with_all_data=True)
39 | db.create_tables()
40 |
41 |
42 | def teardown_database(db):
43 | if db.schema:
44 | db.drop_all_tables(with_all_data=True)
45 | db.disconnect()
46 |
47 |
48 | def only_for(providers):
49 | if not isinstance(providers, (list, tuple)):
50 | providers = [providers]
51 | def decorator(x):
52 | if isinstance(x, type) and issubclass(x, unittest.TestCase):
53 | @classmethod
54 | def setUpClass(cls):
55 | raise unittest.SkipTest('%s tests implemented only for %s provider%s' % (
56 | cls.__name__, ', '.join(providers), '' if len(providers) < 2 else 's'
57 | ))
58 | if db_params['provider'] not in providers:
59 | x.setUpClass = setUpClass
60 | result = x
61 | elif isinstance(x, types.FunctionType):
62 | def new_test_func(self):
63 | if db_params['provider'] not in providers:
64 | raise unittest.SkipTest('%s test implemented only for %s provider%s' % (
65 | x.__name__, ', '.join(providers), '' if len(providers) < 2 else 's'
66 | ))
67 | return x(self)
68 | result = new_test_func
69 | else:
70 | raise TypeError
71 | return result
72 | return decorator
73 |
--------------------------------------------------------------------------------
/pony/orm/tests/aggregate_count_queries.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/orm/tests/aggregate_count_queries.txt
--------------------------------------------------------------------------------
/pony/orm/tests/coverage.bat:
--------------------------------------------------------------------------------
1 | C:\Python33\Scripts\coverage.exe erase
2 |
3 |
4 | C:\Python26\Scripts\coverage.exe run --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch -m unittest discover
5 |
6 | C:\Python27\Scripts\coverage.exe run --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch -m unittest discover
7 |
8 | C:\Python33\Scripts\coverage.exe run --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch -m unittest discover
9 |
10 |
11 | C:\Python26\Scripts\coverage.exe run -a --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch sql_tests.py
12 |
13 | C:\Python27\Scripts\coverage.exe run -a --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch sql_tests.py
14 |
15 | C:\Python33\Scripts\coverage.exe run -a --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch sql_tests.py
16 |
17 |
18 | C:\Python33\Scripts\coverage.exe html
19 |
--------------------------------------------------------------------------------
/pony/orm/tests/coverage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | coverage erase
4 |
5 | coverage-2.7 run --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch -m unittest discover
6 |
7 | coverage-3.4 run --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch -m unittest discover
8 |
9 |
10 | coverage-2.7 run -a --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch sql_tests.py
11 |
12 | coverage-3.4 run -a --source pony.orm.dbapiprovider,pony.orm.dbschema,pony.orm.decompiling,pony.orm.core,pony.orm.sqlbuilding,pony.orm.sqltranslation --branch sql_tests.py
13 |
14 | coverage html
15 |
--------------------------------------------------------------------------------
/pony/orm/tests/model1-database.sql:
--------------------------------------------------------------------------------
1 | drop table if exists Groups;
2 | create table Groups(
3 | number varchar(6) primary key,
4 | department integer not null
5 | );
6 |
7 | drop table if exists Students;
8 | create table Students(
9 | record integer primary key,
10 | fio varchar(50) not null,
11 | [group] varchar(6) not null references Groups(number),
12 | scholarship integer not null default 0
13 | );
14 |
15 | drop table if exists Subjects;
16 | create table Subjects(
17 | name varchar(50) primary key
18 | );
19 |
20 | drop table if exists Group_Subject;
21 | create table Group_Subject(
22 | [group] varchar(6) not null references Groups(number),
23 | subject varchar(50) not null references Subjects(name),
24 | primary key ([group], subject)
25 | );
26 |
27 | drop table if exists Exams;
28 | create table Exams(
29 | student integer not null references Students(number),
30 | subject varchar(50) not null references Subjects(name),
31 | value integer not null,
32 | primary key (student, subject)
33 | );
34 |
35 | insert into Groups values ('4145', 44);
36 | insert into Groups values ('4146', 44);
37 | insert into Groups values ('3132', 33);
38 |
39 | insert into Students values(101, 'Bob', '4145', 0);
40 | insert into Students values(102, 'Joe', '4145', 800);
41 | insert into Students values(103, 'Alex', '4145', 0);
42 | insert into Students values(104, 'Brad', '3132', 500);
43 | insert into Students values(105, 'John', '3132', 1000);
44 |
45 | insert into Subjects values('Physics');
46 | insert into Subjects values('Chemistry');
47 | insert into Subjects values('Math');
48 |
49 | insert into Group_Subject values('4145', 'Physics');
50 | insert into Group_Subject values('4145', 'Chemistry');
51 | insert into Group_Subject values('4145', 'Math');
52 | insert into Group_Subject values('3132', 'Physics');
53 | insert into Group_Subject values('3132', 'Math');
54 |
55 | insert into Exams values (101, 'Physics', 4);
56 | insert into Exams values (101, 'Math', 3);
57 | insert into Exams values (102, 'Chemistry', 5);
58 | insert into Exams values (103, 'Physics', 2);
59 | insert into Exams values (103, 'Chemistry', 4);
60 |
--------------------------------------------------------------------------------
/pony/orm/tests/model1.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | from pony.orm.core import *
4 | from pony.orm.tests import db_params
5 |
6 | db = Database(**db_params)
7 |
8 | class Student(db.Entity):
9 | _table_ = "Students"
10 | record = PrimaryKey(int)
11 | name = Required(str, column="fio")
12 | group = Required("Group")
13 | scholarship = Required(int, default=0)
14 | marks = Set("Mark")
15 |
16 | class Group(db.Entity):
17 | _table_ = "Groups"
18 | number = PrimaryKey(str)
19 | department = Required(int)
20 | students = Set("Student")
21 | subjects = Set("Subject")
22 |
23 | class Subject(db.Entity):
24 | _table_ = "Subjects"
25 | name = PrimaryKey(str)
26 | groups = Set("Group")
27 | marks = Set("Mark")
28 |
29 | class Mark(db.Entity):
30 | _table_ = "Exams"
31 | student = Required(Student, column="student")
32 | subject = Required(Subject, column="subject")
33 | value = Required(int)
34 | PrimaryKey(student, subject)
35 |
36 |
37 | db.generate_mapping(check_tables=False)
38 |
39 |
40 | @db_session
41 | def populate_db():
42 | Physics = Subject(name='Physics')
43 | Chemistry = Subject(name='Chemistry')
44 | Math = Subject(name='Math')
45 |
46 | g3132 = Group(number='3132', department=33, subjects=[ Physics, Math ])
47 | g4145 = Group(number='4145', department=44, subjects=[ Physics, Chemistry, Math ])
48 | g4146 = Group(number='4146', department=44)
49 |
50 | s101 = Student(record=101, name='Bob', group=g4145, scholarship=0)
51 | s102 = Student(record=102, name='Joe', group=g4145, scholarship=800)
52 | s103 = Student(record=103, name='Alex', group=g4145, scholarship=0)
53 | s104 = Student(record=104, name='Brad', group=g3132, scholarship=500)
54 | s105 = Student(record=105, name='John', group=g3132, scholarship=1000)
55 |
56 | Mark(student=s101, subject=Physics, value=4)
57 | Mark(student=s101, subject=Math, value=3)
58 | Mark(student=s102, subject=Chemistry, value=5)
59 | Mark(student=s103, subject=Physics, value=2)
60 | Mark(student=s103, subject=Chemistry, value=4)
61 |
--------------------------------------------------------------------------------
/pony/orm/tests/poster_queries.txt:
--------------------------------------------------------------------------------
1 | Schema:
2 | pony.orm.examples.estore
3 |
4 | >>> x = "joe@example.com"
5 | >>> select((o for o in Order if o.customer.email == x))[:]
6 |
7 | SELECT "o"."id", "o"."state", "o"."date_created", "o"."date_shipped", "o"."date_delivered", "o"."total_price", "o"."customer"
8 | FROM "Order" "o", "Customer" "customer-1"
9 | WHERE "customer-1"."email" = ?
10 | AND "o"."customer" = "customer-1"."id"
11 |
12 | MySQL:
13 |
14 | SELECT `o`.`id`, `o`.`state`, `o`.`date_created`, `o`.`date_shipped`, `o`.`date_delivered`, `o`.`total_price`, `o`.`customer`
15 | FROM `Order` `o`, `Customer` `customer-1`
16 | WHERE `customer-1`.`email` = %s
17 | AND `o`.`customer` = `customer-1`.`id`
18 |
19 | PostgreSQL:
20 |
21 | SELECT "o"."id", "o"."state", "o"."date_created", "o"."date_shipped", "o"."date_delivered", "o"."total_price", "o"."customer"
22 | FROM "order" "o", "customer" "customer-1"
23 | WHERE "customer-1"."email" = %(p1)s
24 | AND "o"."customer" = "customer-1"."id"
25 |
26 | Oracle:
27 |
28 | SELECT "o"."ID", "o"."STATE", "o"."DATE_CREATED", "o"."DATE_SHIPPED", "o"."DATE_DELIVERED", "o"."TOTAL_PRICE", "o"."CUSTOMER"
29 | FROM "ORDER" "o", "CUSTOMER" "customer-1"
30 | WHERE "customer-1"."EMAIL" = :p1
31 | AND "o"."CUSTOMER" = "customer-1"."ID"
32 |
33 | >>> avg(o.total_price for o in Order if o.date_created.year == 2012)
34 |
35 | SELECT AVG("o"."total_price")
36 | FROM "Order" "o"
37 | WHERE cast(substr("o"."date_created", 1, 4) as integer) = 2012
38 |
39 | MySQL:
40 |
41 | SELECT AVG(`o`.`total_price`)
42 | FROM `Order` `o`
43 | WHERE year(`o`.`date_created`) = 2012
44 |
45 | PostgreSQL:
46 |
47 | SELECT AVG("o"."total_price")
48 | FROM "order" "o"
49 | WHERE EXTRACT(YEAR FROM "o"."date_created") = 2012
50 |
51 | Oracle:
52 |
53 | SELECT AVG("o"."TOTAL_PRICE")
54 | FROM "ORDER" "o"
55 | WHERE EXTRACT(YEAR FROM "o"."DATE_CREATED") = 2012
56 |
57 | >>> select((c, sum(c.orders.total_price)) for c in Customer).order_by(lambda c: desc(sum(c.orders.total_price)))[:10]
58 |
59 | SELECT "c"."id", coalesce(SUM("order-1"."total_price"), 0)
60 | FROM "Customer" "c"
61 | LEFT JOIN "Order" "order-1"
62 | ON "c"."id" = "order-1"."customer"
63 | GROUP BY "c"."id"
64 | ORDER BY coalesce(SUM("order-1"."total_price"), 0) DESC
65 | LIMIT 10
66 |
67 | MySQL:
68 |
69 | SELECT `c`.`id`, coalesce(SUM(`order-1`.`total_price`), 0)
70 | FROM `Customer` `c`
71 | LEFT JOIN `Order` `order-1`
72 | ON `c`.`id` = `order-1`.`customer`
73 | GROUP BY `c`.`id`
74 | ORDER BY coalesce(SUM(`order-1`.`total_price`), 0) DESC
75 | LIMIT 10
76 |
77 | PostgreSQL:
78 |
79 | SELECT "c"."id", coalesce(SUM("order-1"."total_price"), 0)
80 | FROM "customer" "c"
81 | LEFT JOIN "order" "order-1"
82 | ON "c"."id" = "order-1"."customer"
83 | GROUP BY "c"."id"
84 | ORDER BY coalesce(SUM("order-1"."total_price"), 0) DESC
85 | LIMIT 10
86 |
87 | Oracle:
88 |
89 | SELECT * FROM (
90 | SELECT "c"."ID", coalesce(SUM("order-1"."TOTAL_PRICE"), 0)
91 | FROM "CUSTOMER" "c"
92 | LEFT JOIN "ORDER" "order-1"
93 | ON "c"."ID" = "order-1"."CUSTOMER"
94 | GROUP BY "c"."ID"
95 | ORDER BY coalesce(SUM("order-1"."TOTAL_PRICE"), 0) DESC
96 | ) WHERE ROWNUM <= 10
97 |
--------------------------------------------------------------------------------
/pony/orm/tests/sql_tests.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import re, os, os.path, sys
4 | from datetime import datetime, timedelta
5 |
6 | from pony import orm
7 | from pony.orm import core
8 | from pony.orm.tests import testutils
9 |
10 | core.suppress_debug_change = True
11 |
12 | directive_re = re.compile(r'(\w+)(\s+[0-9\.]+)?:')
13 | directive = module_name = None
14 | statements = []
15 | lines = []
16 |
17 | def Schema(param):
18 | if not statement_used:
19 | print()
20 | print('Statement not used:')
21 | print()
22 | print('\n'.join(statements))
23 | print()
24 | sys.exit()
25 | assert len(lines) == 1
26 | global module_name
27 | module_name = lines[0].strip()
28 |
29 | def SQLite(server_version):
30 | do_test('sqlite', server_version)
31 |
32 | def MySQL(server_version):
33 | do_test('mysql', server_version)
34 |
35 | def PostgreSQL(server_version):
36 | do_test('postgres', server_version)
37 |
38 | def Oracle(server_version):
39 | do_test('oracle', server_version)
40 |
41 | unavailable_providers = set()
42 |
43 | def do_test(provider_name, raw_server_version):
44 | if provider_name in unavailable_providers: return
45 | testutils.TestDatabase.real_provider_name = provider_name
46 | testutils.TestDatabase.raw_server_version = raw_server_version
47 | core.Database = orm.Database = testutils.TestDatabase
48 | sys.modules.pop(module_name, None)
49 | try: __import__(module_name)
50 | except ImportError as e:
51 | print()
52 | print('ImportError for database provider %s:\n%s' % (provider_name, e))
53 | print()
54 | unavailable_providers.add(provider_name)
55 | return
56 | module = sys.modules[module_name]
57 | globals = vars(module).copy()
58 | globals.update(datetime=datetime, timedelta=timedelta)
59 | with orm.db_session:
60 | for statement in statements[:-1]:
61 | code = compile(statement, '', 'exec')
62 | exec(code, globals)
63 | statement = statements[-1]
64 | try: last_code = compile(statement, '', 'eval')
65 | except SyntaxError:
66 | last_code = compile(statement, '', 'exec')
67 | exec(last_code, globals)
68 | else:
69 | result = eval(last_code, globals)
70 | if isinstance(result, core.Query): result = list(result)
71 | sql = module.db.sql
72 | expected_sql = '\n'.join(lines)
73 | if sql == expected_sql: print('.', end='')
74 | else:
75 | print()
76 | print(provider_name, statements[-1])
77 | print()
78 | print('Expected:')
79 | print(expected_sql)
80 | print()
81 | print('Got:')
82 | print(sql)
83 | print()
84 | global statement_used
85 | statement_used = True
86 |
87 | dirname, fname = os.path.split(__file__)
88 | queries_fname = os.path.join(dirname, 'queries.txt')
89 |
90 | def orphan_lines(lines):
91 | SQLite(None)
92 | lines[:] = []
93 |
94 | statement_used = True
95 | for raw_line in open(queries_fname):
96 | line = raw_line.strip()
97 | if not line: continue
98 | if line.startswith('#'): continue
99 | match = directive_re.match(line)
100 | if match:
101 | if directive:
102 | directive(directive_param)
103 | lines[:] = []
104 | elif lines: orphan_lines(lines)
105 | directive = eval(match.group(1))
106 | if match.group(2):
107 | directive_param = match.group(2)
108 | else: directive_param = None
109 | elif line.startswith('>>> '):
110 | if directive:
111 | directive(directive_param)
112 | lines[:] = []
113 | statements[:] = []
114 | elif lines: orphan_lines(lines)
115 | directive = None
116 | directive_param = None
117 | statements.append(line[4:])
118 | statement_used = False
119 | else:
120 | lines.append(raw_line.rstrip())
121 |
122 | if directive:
123 | directive(directive_param)
124 | elif lines:
125 | orphan_lines(lines)
126 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_attribute_options.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from decimal import Decimal
3 | from datetime import datetime, time
4 | from random import randint
5 |
6 | from pony import orm
7 | from pony.orm.core import *
8 | from pony.orm.tests import setup_database, teardown_database
9 | from pony.orm.tests.testutils import raises_exception
10 |
11 | db = Database()
12 |
13 | class Person(db.Entity):
14 | id = PrimaryKey(int)
15 | name = orm.Required(str, 40)
16 | lastName = orm.Required(str, max_len=40, unique=True)
17 | age = orm.Optional(int, max=60, min=10)
18 | nickName = orm.Optional(str, autostrip=False)
19 | middleName = orm.Optional(str, nullable=True)
20 | rate = orm.Optional(Decimal, precision=11)
21 | salaryRate = orm.Optional(Decimal, precision=13, scale=8)
22 | timeStmp = orm.Optional(datetime, precision=6)
23 | gpa = orm.Optional(float, py_check=lambda val: val >= 0 and val <= 5)
24 | vehicle = orm.Optional(str, column='car')
25 |
26 | class TestAttributeOptions(unittest.TestCase):
27 | @classmethod
28 | def setUpClass(cls):
29 | setup_database(db)
30 | with orm.db_session:
31 | p1 = Person(id=1, name='Andrew', lastName='Bodroue', age=40, rate=0.980000000001, salaryRate=0.98000001)
32 | p2 = Person(id=2, name='Vladimir', lastName='Andrew ', nickName='vlad ')
33 | p3 = Person(id=3, name='Nick', lastName='Craig', middleName=None, timeStmp='2010-12-10 14:12:09.019473',
34 | vehicle='dodge')
35 |
36 | @classmethod
37 | def tearDownClass(cls):
38 | teardown_database(db)
39 |
40 | def setUp(self):
41 | rollback()
42 | db_session.__enter__()
43 |
44 | def tearDown(self):
45 | rollback()
46 | db_session.__exit__()
47 |
48 | def test_optionalStringEmpty(self):
49 | queryResult = select(p.id for p in Person if p.nickName==None).first()
50 | self.assertIsNone(queryResult)
51 |
52 | def test_optionalStringNone(self):
53 | queryResult = select(p.id for p in Person if p.middleName==None).first()
54 | self.assertIsNotNone(queryResult)
55 |
56 | def test_stringAutoStrip(self):
57 | self.assertEqual(Person[2].lastName, 'Andrew')
58 |
59 | def test_stringAutoStripFalse(self):
60 | self.assertEqual(Person[2].nickName, 'vlad ')
61 |
62 | def test_intNone(self):
63 | queryResult = select(p.id for p in Person if p.age==None).first()
64 | self.assertIsNotNone(queryResult)
65 |
66 | def test_columnName(self):
67 | self.assertEqual(getattr(Person.vehicle, 'column'), 'car')
68 |
69 | def test_decimalPrecisionTwo(self):
70 | queryResult = select(p.rate for p in Person if p.age==40).first()
71 | self.assertAlmostEqual(float(queryResult), 0.98, 12)
72 |
73 | def test_decimalPrecisionEight(self):
74 | queryResult = select(p.salaryRate for p in Person if p.age==40).first()
75 | self.assertAlmostEqual(float(queryResult), 0.98000001, 8)
76 |
77 | def test_fractionalSeconds(self):
78 | queryResult = select(p.timeStmp for p in Person if p.name=='Nick').first()
79 | self.assertEqual(queryResult.microsecond, 19473)
80 |
81 | def test_intMax(self):
82 | p4 = Person(id=4, name='Denis', lastName='Blanc', age=60)
83 |
84 | def test_intMin(self):
85 | p4 = Person(id=4, name='Denis', lastName='Blanc', age=10)
86 |
87 | @raises_exception(ValueError, "Value 61 of attr Person.age is greater than the maximum allowed value 60")
88 | def test_intMaxException(self):
89 | p4 = Person(id=4, name='Denis', lastName='Blanc', age=61)
90 |
91 | @raises_exception(ValueError, "Value 9 of attr Person.age is less than the minimum allowed value 10")
92 | def test_intMinException(self):
93 | p4 = Person(id=4, name='Denis', lastName='Blanc', age=9)
94 |
95 | def test_py_check(self):
96 | p4 = Person(id=4, name='Denis', lastName='Blanc', gpa=5)
97 | p5 = Person(id=5, name='Mario', lastName='Gon', gpa=1)
98 | flush()
99 |
100 | @raises_exception(ValueError, "Check for attribute Person.gpa failed. Value: 6.0")
101 | def test_py_checkMoreException(self):
102 | p6 = Person(id=6, name='Daniel', lastName='Craig', gpa=6)
103 |
104 | @raises_exception(ValueError, "Check for attribute Person.gpa failed. Value: -1.0")
105 | def test_py_checkLessException(self):
106 | p6 = Person(id=6, name='Daniel', lastName='Craig', gpa=-1)
107 |
108 | @raises_exception(TransactionIntegrityError,
109 | 'Object Person[...] cannot be stored in the database. IntegrityError: ...')
110 | def test_unique(self):
111 | p6 = Person(id=6, name='Boris', lastName='Bodroue')
112 | flush()
113 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_autostrip.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests.testutils import raises_exception
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 | class Person(db.Entity):
10 | name = Required(str)
11 | tel = Optional(str)
12 |
13 |
14 | class TestAutostrip(unittest.TestCase):
15 | @classmethod
16 | def setUpClass(cls):
17 | setup_database(db)
18 |
19 | @classmethod
20 | def tearDownClass(cls):
21 | teardown_database(db)
22 |
23 | @db_session
24 | def test_1(self):
25 | p = Person(name=' John ', tel=' ')
26 | p.flush()
27 | self.assertEqual(p.name, 'John')
28 | self.assertEqual(p.tel, '')
29 |
30 | @raises_exception(ValueError, 'Attribute Person.name is required')
31 | @db_session
32 | def test_2(self):
33 | p = Person(name=' ')
34 |
35 | if __name__ == '__main__':
36 | unittest.main()
37 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_buffer.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony import orm
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 | db = orm.Database()
7 |
8 |
9 | class Foo(db.Entity):
10 | id = orm.PrimaryKey(int)
11 | b = orm.Optional(orm.buffer)
12 |
13 |
14 | class Bar(db.Entity):
15 | b = orm.PrimaryKey(orm.buffer)
16 |
17 |
18 | class Baz(db.Entity):
19 | id = orm.PrimaryKey(int)
20 | b = orm.Optional(orm.buffer, unique=True)
21 |
22 |
23 | buf = orm.buffer(b'123')
24 |
25 | class Test(unittest.TestCase):
26 | @classmethod
27 | def setUpClass(cls):
28 | setup_database(db)
29 | with orm.db_session:
30 | Foo(id=1, b=buf)
31 | Bar(b=buf)
32 | Baz(id=1, b=buf)
33 |
34 | @classmethod
35 | def tearDownClass(cls):
36 | teardown_database(db)
37 |
38 | def test_1(self): # Bug #355
39 | with orm.db_session:
40 | Bar[buf]
41 |
42 | def test_2(self): # Regression after #355 fix
43 | with orm.db_session:
44 | result = orm.select(bar.b for bar in Foo)[:]
45 | self.assertEqual(result, [buf])
46 |
47 | def test_3(self): # Bug #390
48 | with orm.db_session:
49 | Baz.get(b=buf)
50 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_bug_170.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony import orm
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 | db = orm.Database()
7 |
8 |
9 | class Person(db.Entity):
10 | id = orm.PrimaryKey(int, auto=True)
11 | name = orm.Required(str)
12 | orm.composite_key(id, name)
13 |
14 |
15 | class Test(unittest.TestCase):
16 | @classmethod
17 | def setUpClass(cls):
18 | setup_database(db)
19 |
20 | @classmethod
21 | def tearDownClass(cls):
22 | teardown_database(db)
23 |
24 | def test_1(self):
25 | table = db.schema.tables[Person._table_]
26 | pk_column = table.column_dict[Person.id.column]
27 | self.assertTrue(pk_column.is_pk)
28 |
29 | with orm.db_session:
30 | p1 = Person(name='John')
31 | p2 = Person(name='Mike')
32 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_bug_182.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony import orm
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 |
10 | class User(db.Entity):
11 | name = Required(str)
12 | servers = Set("Server")
13 |
14 |
15 | class Worker(User):
16 | pass
17 |
18 |
19 | class Admin(Worker):
20 | pass
21 |
22 | # And M:1 relationship with another entity
23 | class Server(db.Entity):
24 | name = Required(str)
25 | user = Optional(User)
26 |
27 |
28 | class Test(unittest.TestCase):
29 | @classmethod
30 | def setUpClass(cls):
31 | setup_database(db)
32 | with orm.db_session:
33 | Server(name='s1.example.com', user=User(name="Alex"))
34 | Server(name='s2.example.com', user=Worker(name="John"))
35 | Server(name='free.example.com', user=None)
36 |
37 | @classmethod
38 | def tearDownClass(cls):
39 | teardown_database(db)
40 |
41 | @db_session
42 | def test(self):
43 | qu = left_join((s.name, s.user.name) for s in db.Server)[:]
44 | for server, user in qu:
45 | if user is None:
46 | break
47 | else:
48 | self.fail()
49 |
50 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_bug_331.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm.tests import setup_database, teardown_database
4 | from pony.orm import *
5 |
6 | db = Database()
7 |
8 |
9 | class Person(db.Entity):
10 | name = Required(str)
11 | group = Optional(lambda: Group)
12 |
13 |
14 | class Group(db.Entity):
15 | title = PrimaryKey(str)
16 | persons = Set(Person)
17 |
18 | def __len__(self):
19 | return len(self.persons)
20 |
21 |
22 | class Test(unittest.TestCase):
23 | @classmethod
24 | def setUpClass(cls):
25 | setup_database(db)
26 |
27 | @classmethod
28 | def tearDownClass(cls):
29 | teardown_database(db)
30 |
31 | def test_1(self):
32 | with db_session:
33 | p1 = Person(name="Alex")
34 | p2 = Person(name="Brad")
35 | p3 = Person(name="Chad")
36 | p4 = Person(name="Dylan")
37 | p5 = Person(name="Ethan")
38 |
39 | g1 = Group(title="Foxes")
40 | g2 = Group(title="Gorillas")
41 |
42 | g1.persons.add(p1)
43 | g1.persons.add(p2)
44 | g1.persons.add(p3)
45 | g2.persons.add(p4)
46 | g2.persons.add(p5)
47 | commit()
48 |
49 | foxes = Group['Foxes']
50 | gorillas = Group['Gorillas']
51 |
52 | self.assertEqual(len(foxes), 3)
53 | self.assertEqual(len(gorillas), 2)
54 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_bug_386.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony import orm
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 | db = orm.Database()
7 |
8 |
9 | class Person(db.Entity):
10 | name = orm.Required(str)
11 |
12 |
13 | class Test(unittest.TestCase):
14 | @classmethod
15 | def setUpClass(cls):
16 | setup_database(db)
17 |
18 | @classmethod
19 | def tearDownClass(cls):
20 | teardown_database(db)
21 |
22 | def test_1(self):
23 | with orm.db_session:
24 | a = Person(name='John')
25 | a.delete()
26 | Person.exists(name='Mike')
27 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_cascade.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests.testutils import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 |
8 | class TestCascade(unittest.TestCase):
9 | providers = ['sqlite'] # Implement for other providers
10 |
11 | def tearDown(self):
12 | if self.db.schema is not None:
13 | teardown_database(self.db)
14 |
15 | def assert_on_delete(self, table_name, value):
16 | db = self.db
17 | if not (db.provider.dialect == 'SQLite' and pony.__version__ < '0.9'):
18 | table_name = table_name.lower()
19 | table = db.schema.tables[table_name]
20 | fkeys = table.foreign_keys
21 | self.assertEqual(1, len(fkeys))
22 | if pony.__version__ >= '0.9':
23 | self.assertEqual(fkeys[0].on_delete, value)
24 | elif db.provider.dialect == 'SQLite':
25 | self.assertIn('ON DELETE %s' % value, table.get_create_command())
26 | else:
27 | self.assertIn('ON DELETE %s' % value, list(fkeys.values())[0].get_create_command())
28 |
29 |
30 | def test_1(self):
31 | db = self.db = Database()
32 |
33 | class Person(self.db.Entity):
34 | name = Required(str)
35 | group = Required('Group')
36 |
37 | class Group(self.db.Entity):
38 | persons = Set(Person)
39 |
40 | setup_database(db)
41 | self.assert_on_delete('Person', 'CASCADE')
42 |
43 | def test_2(self):
44 | db = self.db = Database()
45 |
46 | class Person(self.db.Entity):
47 | name = Required(str)
48 | group = Required('Group')
49 |
50 | class Group(self.db.Entity):
51 | persons = Set(Person, cascade_delete=True)
52 |
53 | setup_database(db)
54 | self.assert_on_delete('Person', 'CASCADE')
55 |
56 | def test_3(self):
57 | db = self.db = Database()
58 |
59 | class Person(self.db.Entity):
60 | name = Required(str)
61 | group = Optional('Group')
62 |
63 | class Group(self.db.Entity):
64 | persons = Set(Person, cascade_delete=True)
65 |
66 | setup_database(db)
67 | self.assert_on_delete('Person', 'CASCADE')
68 |
69 | @raises_exception(TypeError, "'cascade_delete' option cannot be set for attribute Group.persons, because reverse attribute Person.group is collection")
70 | def test_4(self):
71 | db = self.db = Database()
72 |
73 | class Person(self.db.Entity):
74 | name = Required(str)
75 | group = Set('Group')
76 |
77 | class Group(self.db.Entity):
78 | persons = Set(Person, cascade_delete=True)
79 |
80 | setup_database(db)
81 |
82 | @raises_exception(TypeError, "'cascade_delete' option cannot be set for both sides of relationship (Person.group and Group.persons) simultaneously")
83 | def test_5(self):
84 | db = self.db = Database()
85 |
86 | class Person(self.db.Entity):
87 | name = Required(str)
88 | group = Set('Group', cascade_delete=True)
89 |
90 | class Group(self.db.Entity):
91 | persons = Required(Person, cascade_delete=True)
92 |
93 | setup_database(db)
94 |
95 | def test_6(self):
96 | db = self.db = Database()
97 |
98 | class Person(self.db.Entity):
99 | name = Required(str)
100 | group = Set('Group')
101 |
102 | class Group(self.db.Entity):
103 | persons = Optional(Person)
104 |
105 | setup_database(db)
106 | self.assert_on_delete('Group', 'SET NULL')
107 |
108 |
109 | if __name__ == '__main__':
110 | unittest.main()
111 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_cascade_delete.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests import setup_database, teardown_database, only_for
5 |
6 | db = Database()
7 |
8 | class X(db.Entity):
9 | id = PrimaryKey(int)
10 | parent = Optional('X', reverse='children')
11 | children = Set('X', reverse='parent', cascade_delete=True)
12 |
13 |
14 | class Y(db.Entity):
15 | parent = Optional('Y', reverse='children')
16 | children = Set('Y', reverse='parent', cascade_delete=True, lazy=True)
17 |
18 |
19 | class TestCascade(unittest.TestCase):
20 | @classmethod
21 | def setUpClass(cls):
22 | setup_database(db)
23 | with db_session:
24 | x1 = X(id=1)
25 | x2 = X(id=2, parent=x1)
26 | x3 = X(id=3, parent=x1)
27 | x4 = X(id=4, parent=x3)
28 | x5 = X(id=5, parent=x3)
29 | x6 = X(id=6, parent=x5)
30 | x7 = X(id=7, parent=x3)
31 | x8 = X(id=8, parent=x7)
32 | x9 = X(id=9, parent=x7)
33 | x10 = X(id=10)
34 | x11 = X(id=11, parent=x10)
35 | x12 = X(id=12, parent=x10)
36 |
37 | y1 = Y(id=1)
38 | y2 = Y(id=2, parent=y1)
39 | y3 = Y(id=3, parent=y1)
40 | y4 = Y(id=4, parent=y3)
41 | y5 = Y(id=5, parent=y3)
42 | y6 = Y(id=6, parent=y5)
43 | y7 = Y(id=7, parent=y3)
44 | y8 = Y(id=8, parent=y7)
45 | y9 = Y(id=9, parent=y7)
46 | y10 = Y(id=10)
47 | y11 = Y(id=11, parent=y10)
48 | y12 = Y(id=12, parent=y10)
49 |
50 | @classmethod
51 | def tearDownClass(cls):
52 | teardown_database(db)
53 |
54 | def setUp(self):
55 | rollback()
56 | db_session.__enter__()
57 |
58 | def tearDown(self):
59 | rollback()
60 | db_session.__exit__()
61 |
62 | def test_1(self):
63 | db.merge_local_stats()
64 | X[1].delete()
65 | stats = db.local_stats[None]
66 | self.assertEqual(5, stats.db_count)
67 |
68 | def test_2(self):
69 | db.merge_local_stats()
70 | Y[1].delete()
71 | stats = db.local_stats[None]
72 | self.assertEqual(10, stats.db_count)
73 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_collections.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.tests.testutils import raises_exception
6 | from pony.orm.tests.model1 import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 |
10 | class TestCollections(unittest.TestCase):
11 | @classmethod
12 | def setUpClass(cls):
13 | setup_database(db)
14 | populate_db()
15 |
16 | @classmethod
17 | def tearDownClass(cls):
18 | db.drop_all_tables(with_all_data=True)
19 |
20 | @db_session
21 | def test_setwrapper_len(self):
22 | g = Group.get(number='4145')
23 | self.assertTrue(len(g.students) == 3)
24 |
25 | @db_session
26 | def test_setwrapper_nonzero(self):
27 | g = Group.get(number='4145')
28 | self.assertTrue(bool(g.students) == True)
29 | self.assertTrue(len(g.students) == 3)
30 |
31 | @db_session
32 | @raises_exception(TypeError, 'Collection attribute Group.students cannot be specified as search criteria')
33 | def test_get_by_collection_error(self):
34 | Group.get(students=[])
35 |
36 | @db_session
37 | def test_collection_create_one2many_1(self):
38 | g = Group['3132']
39 | g.students.create(record=106, name='Mike', scholarship=200)
40 | flush()
41 | self.assertEqual(len(g.students), 3)
42 | rollback()
43 |
44 | @raises_exception(TypeError, "When using Group.students.create(), "
45 | "'group' attribute should not be passed explicitly")
46 | @db_session
47 | def test_collection_create_one2many_2(self):
48 | g = Group['3132']
49 | g.students.create(record=106, name='Mike', scholarship=200, group=g)
50 |
51 | @raises_exception(TransactionIntegrityError, "Object Student[105] cannot be stored in the database...")
52 | @db_session
53 | def test_collection_create_one2many_3(self):
54 | g = Group['3132']
55 | g.students.create(record=105, name='Mike', scholarship=200)
56 |
57 | @db_session
58 | def test_collection_create_many2many_1(self):
59 | g = Group['3132']
60 | g.subjects.create(name='Biology')
61 | flush()
62 | self.assertEqual(len(g.subjects), 3)
63 | rollback()
64 |
65 | @raises_exception(TypeError, "When using Group.subjects.create(), "
66 | "'groups' attribute should not be passed explicitly")
67 | @db_session
68 | def test_collection_create_many2many_2(self):
69 | g = Group['3132']
70 | g.subjects.create(name='Biology', groups=[g])
71 |
72 | @raises_exception(TransactionIntegrityError, "Object Subject['Math'] cannot be stored in the database...")
73 | @db_session
74 | def test_collection_create_many2many_3(self):
75 | g = Group['3132']
76 | g.subjects.create(name='Math')
77 |
78 | # replace collection items when the old ones are not fully loaded
79 | ##>>> from pony.examples.orm.students01.model import *
80 | ##>>> s1 = Student[101]
81 | ##>>> g = s1.group
82 | ##>>> g.__dict__[Group.students].is_fully_loaded
83 | ##False
84 | ##>>> s2 = Student[104]
85 | ##>>> g.students = [s2]
86 | ##>>>
87 |
88 | # replace collection items when the old ones are not loaded
89 | ##>>> from pony.examples.orm.students01.model import *
90 | ##>>> g = Group[4145]
91 | ##>>> Group.students not in g.__dict__
92 | ##True
93 | ##>>> s2 = Student[104]
94 | ##>>> g.students = [s2]
95 |
96 |
97 | if __name__ == '__main__':
98 | unittest.main()
99 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_conversions.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from datetime import timedelta
3 |
4 | from pony import converting
5 |
6 | class Test(unittest.TestCase):
7 | def test_timestamps_1(self):
8 | s = '1:2:3'
9 | td = converting.str2timedelta(s)
10 | self.assertEqual(td, timedelta(hours=1, minutes=2, seconds=3))
11 | s = '01:02:03'
12 | td = converting.str2timedelta(s)
13 | self.assertEqual(td, timedelta(hours=1, minutes=2, seconds=3))
14 | s = '1:2:3.456'
15 | td = converting.str2timedelta(s)
16 | self.assertEqual(td, timedelta(hours=1, minutes=2, seconds=3, milliseconds=456))
17 | s = '1:2:3.45678'
18 | td = converting.str2timedelta(s)
19 | self.assertEqual(td, timedelta(hours=1, minutes=2, seconds=3, microseconds=456780))
20 | s = '12:34:56'
21 | td = converting.str2timedelta(s)
22 | self.assertEqual(td, timedelta(hours=12, minutes=34, seconds=56))
23 | s = '12:34:56.789'
24 | td = converting.str2timedelta(s)
25 | self.assertEqual(td, timedelta(hours=12, minutes=34, seconds=56, milliseconds=789))
26 | s = '12:34:56.789123'
27 | td = converting.str2timedelta(s)
28 | self.assertEqual(td, timedelta(hours=12, minutes=34, seconds=56, microseconds=789123))
29 |
30 | def test_timestamps_2(self):
31 | s = '-1:2:3'
32 | td = converting.str2timedelta(s)
33 | self.assertEqual(td, -timedelta(hours=1, minutes=2, seconds=3))
34 | s = '-01:02:03'
35 | td = converting.str2timedelta(s)
36 | self.assertEqual(td, -timedelta(hours=1, minutes=2, seconds=3))
37 | s = '-1:2:3.456'
38 | td = converting.str2timedelta(s)
39 | self.assertEqual(td, -timedelta(hours=1, minutes=2, seconds=3, milliseconds=456))
40 | s = '-1:2:3.45678'
41 | td = converting.str2timedelta(s)
42 | self.assertEqual(td, -timedelta(hours=1, minutes=2, seconds=3, microseconds=456780))
43 | s = '-12:34:56'
44 | td = converting.str2timedelta(s)
45 | self.assertEqual(td, -timedelta(hours=12, minutes=34, seconds=56))
46 | s = '-12:34:56.789'
47 | td = converting.str2timedelta(s)
48 | self.assertEqual(td, -timedelta(hours=12, minutes=34, seconds=56, milliseconds=789))
49 | s = '-12:34:56.789123'
50 | td = converting.str2timedelta(s)
51 | self.assertEqual(td, -timedelta(hours=12, minutes=34, seconds=56, microseconds=789123))
52 |
53 | def test_timestamps_3(self):
54 | s = '0:1:2'
55 | td = converting.str2timedelta(s)
56 | self.assertEqual(td, timedelta(minutes=1, seconds=2))
57 | s = '0:1:2.3456'
58 | td = converting.str2timedelta(s)
59 | self.assertEqual(td, timedelta(minutes=1, seconds=2, microseconds=345600))
60 |
61 | def test_timestamps_4(self):
62 | s = '-0:1:2'
63 | td = converting.str2timedelta(s)
64 | self.assertEqual(td, -timedelta(minutes=1, seconds=2))
65 | s = '-0:1:2.3456'
66 | td = converting.str2timedelta(s)
67 | self.assertEqual(td, -timedelta(minutes=1, seconds=2, microseconds=345600))
68 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_core_multiset.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import pickle, unittest
4 |
5 |
6 | from pony.orm.core import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 | db = Database()
10 |
11 | class Department(db.Entity):
12 | number = PrimaryKey(int)
13 | groups = Set('Group')
14 | courses = Set('Course')
15 |
16 | class Group(db.Entity):
17 | number = PrimaryKey(int)
18 | department = Required(Department)
19 | students = Set('Student')
20 |
21 | class Student(db.Entity):
22 | name = Required(str)
23 | group = Required(Group)
24 | courses = Set('Course')
25 |
26 | class Course(db.Entity):
27 | name = PrimaryKey(str)
28 | department = Required(Department)
29 | students = Set('Student')
30 |
31 |
32 | class TestMultiset(unittest.TestCase):
33 |
34 | @classmethod
35 | def setUpClass(cls):
36 | setup_database(db)
37 |
38 | with db_session:
39 | d1 = Department(number=1)
40 | d2 = Department(number=2)
41 | d3 = Department(number=3)
42 |
43 | g1 = Group(number=101, department=d1)
44 | g2 = Group(number=102, department=d1)
45 | g3 = Group(number=201, department=d2)
46 |
47 | c1 = Course(name='C1', department=d1)
48 | c2 = Course(name='C2', department=d1)
49 | c3 = Course(name='C3', department=d2)
50 | c4 = Course(name='C4', department=d2)
51 | c5 = Course(name='C5', department=d3)
52 |
53 | s1 = Student(name='S1', group=g1, courses=[c1, c2])
54 | s2 = Student(name='S2', group=g1, courses=[c1, c3])
55 | s3 = Student(name='S3', group=g1, courses=[c2, c3])
56 |
57 | s4 = Student(name='S4', group=g2, courses=[c1, c2])
58 | s5 = Student(name='S5', group=g2, courses=[c1, c2])
59 |
60 | s6 = Student(name='A', group=g3, courses=[c5])
61 |
62 | @classmethod
63 | def tearDownClass(cls):
64 | teardown_database(db)
65 |
66 | @db_session
67 | def test_multiset_repr_1(self):
68 | d = Department[1]
69 | multiset = d.groups.students
70 | self.assertEqual(repr(multiset), "")
71 |
72 | @db_session
73 | def test_multiset_repr_2(self):
74 | g = Group[101]
75 | multiset = g.students.courses
76 | self.assertEqual(repr(multiset), "")
77 |
78 | @db_session
79 | def test_multiset_repr_3(self):
80 | g = Group[201]
81 | multiset = g.students.courses
82 | self.assertEqual(repr(multiset), "")
83 |
84 | def test_multiset_repr_4(self):
85 | with db_session:
86 | g = Group[101]
87 | multiset = g.students.courses
88 | self.assertIsNone(multiset._obj_._session_cache_)
89 | self.assertEqual(repr(multiset), "")
90 |
91 | @db_session
92 | def test_multiset_str(self):
93 | g = Group[101]
94 | multiset = g.students.courses
95 | self.assertEqual(str(multiset), "CourseMultiset({Course[%r]: 2, Course[%r]: 2, Course[%r]: 2})"
96 | % (u'C1', u'C2', u'C3'))
97 |
98 | @db_session
99 | def test_multiset_distinct(self):
100 | d = Department[1]
101 | multiset = d.groups.students.courses
102 | self.assertEqual(multiset.distinct(), {Course['C1']: 4, Course['C2']: 4, Course['C3']: 2})
103 |
104 | @db_session
105 | def test_multiset_nonzero(self):
106 | d = Department[1]
107 | multiset = d.groups.students
108 | self.assertEqual(bool(multiset), True)
109 |
110 | @db_session
111 | def test_multiset_len(self):
112 | d = Department[1]
113 | multiset = d.groups.students.courses
114 | self.assertEqual(len(multiset), 10)
115 |
116 | @db_session
117 | def test_multiset_eq(self):
118 | d = Department[1]
119 | multiset = d.groups.students.courses
120 | c1, c2, c3 = Course['C1'], Course['C2'], Course['C3']
121 | self.assertEqual(multiset, multiset)
122 | self.assertEqual(multiset, {c1: 4, c2: 4, c3: 2})
123 | self.assertEqual(multiset, [ c1, c1, c1, c2, c2, c2, c2, c3, c3, c1 ])
124 |
125 | @db_session
126 | def test_multiset_ne(self):
127 | d = Department[1]
128 | multiset = d.groups.students.courses
129 | self.assertFalse(multiset != multiset)
130 |
131 | @db_session
132 | def test_multiset_contains(self):
133 | d = Department[1]
134 | multiset = d.groups.students.courses
135 | self.assertTrue(Course['C1'] in multiset)
136 | self.assertFalse(Course['C5'] in multiset)
137 |
138 | def test_multiset_reduce(self):
139 | with db_session:
140 | d = Department[1]
141 | multiset = d.groups.students
142 | s = pickle.dumps(multiset)
143 | with db_session:
144 | d = Department[1]
145 | multiset_2 = d.groups.students
146 | multiset_1 = pickle.loads(s)
147 | self.assertEqual(multiset_1, multiset_2)
148 |
149 |
150 | if __name__ == '__main__':
151 | unittest.main()
152 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_crud_raw_sql.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import raises_exception
7 | from pony.orm.tests import setup_database, teardown_database, only_for
8 |
9 | db = Database()
10 |
11 | class Student(db.Entity):
12 | name = Required(str)
13 | age = Optional(int)
14 | friends = Set("Student", reverse='friends')
15 | group = Required("Group")
16 | bio = Optional("Bio")
17 |
18 | class Group(db.Entity):
19 | dept = Required(int)
20 | grad_year = Required(int)
21 | students = Set(Student)
22 | PrimaryKey(dept, grad_year)
23 |
24 | class Bio(db.Entity):
25 | picture = Optional(buffer)
26 | desc = Required(str)
27 | Student = Required(Student)
28 |
29 |
30 | @only_for('sqlite')
31 | class TestCrudRawSQL(unittest.TestCase):
32 | @classmethod
33 | def setUpClass(cls):
34 | setup_database(db)
35 |
36 | @classmethod
37 | def tearDownClass(cls):
38 | teardown_database(db)
39 |
40 | def setUp(self):
41 | with db_session:
42 | db.execute('delete from Student')
43 | db.execute('delete from "Group"')
44 | db.insert(Group, dept=44, grad_year=1999)
45 | db.insert(Student, id=1, name='A', age=30, group_dept=44, group_grad_year=1999)
46 | db.insert(Student, id=2, name='B', age=25, group_dept=44, group_grad_year=1999)
47 | db.insert(Student, id=3, name='C', age=20, group_dept=44, group_grad_year=1999)
48 | rollback()
49 | db_session.__enter__()
50 |
51 | def tearDown(self):
52 | rollback()
53 | db_session.__exit__()
54 |
55 | def test1(self):
56 | students = set(Student.select_by_sql("select id, name, age, group_dept, group_grad_year from Student order by age"))
57 | self.assertEqual(students, {Student[3], Student[2], Student[1]})
58 |
59 | def test2(self):
60 | students = set(Student.select_by_sql("select id, age, group_dept from Student order by age"))
61 | self.assertEqual(students, {Student[3], Student[2], Student[1]})
62 |
63 | @raises_exception(NameError, "Column x does not belong to entity Student")
64 | def test3(self):
65 | students = set(Student.select_by_sql("select id, age, age*2 as x from Student order by age"))
66 | self.assertEqual(students, {Student[3], Student[2], Student[1]})
67 |
68 | @raises_exception(TypeError, 'The first positional argument must be lambda function or its text source. Got: 123')
69 | def test4(self):
70 | students = Student.select(123)
71 |
72 | def test5(self):
73 | x = 1
74 | y = 30
75 | cursor = db.execute("select name from Student where id = $x and age = $y")
76 | self.assertEqual(cursor.fetchone()[0], 'A')
77 |
78 | def test6(self):
79 | x = 1
80 | y = 30
81 | cursor = db.execute("select name, 'abc$$def%' from Student where id = $x and age = $y")
82 | self.assertEqual(cursor.fetchone(), ('A', 'abc$def%'))
83 |
84 | def test7(self):
85 | cursor = db.execute("select name, 'abc$$def%' from Student where id = 1")
86 | self.assertEqual(cursor.fetchone(), ('A', 'abc$def%'))
87 |
88 |
89 | if __name__ == '__main__':
90 | unittest.main()
91 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_datetime.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from datetime import date, datetime, timedelta
5 |
6 | from pony.orm.core import *
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import setup_database, teardown_database
9 |
10 | db = Database()
11 |
12 |
13 | class Entity1(db.Entity):
14 | id = PrimaryKey(int)
15 | d = Required(date)
16 | dt = Required(datetime)
17 |
18 |
19 | class TestDate(unittest.TestCase):
20 | @classmethod
21 | def setUpClass(cls):
22 | setup_database(db)
23 | with db_session:
24 | Entity1(id=1, d=date(2009, 10, 20), dt=datetime(2009, 10, 20, 10, 20, 30))
25 | Entity1(id=2, d=date(2010, 10, 21), dt=datetime(2010, 10, 21, 10, 21, 31))
26 | Entity1(id=3, d=date(2011, 11, 22), dt=datetime(2011, 11, 22, 10, 20, 32))
27 |
28 | @classmethod
29 | def tearDownClass(cls):
30 | teardown_database(db)
31 |
32 | def setUp(self):
33 | rollback()
34 | db_session.__enter__()
35 |
36 | def tearDown(self):
37 | rollback()
38 | db_session.__exit__()
39 |
40 | def test_create(self):
41 | e1 = Entity1(id=4, d=date(2011, 10, 20), dt=datetime(2009, 10, 20, 10, 20, 30))
42 |
43 | def test_date_year(self):
44 | result = select(e for e in Entity1 if e.d.year > 2009)
45 | self.assertEqual(len(result), 2)
46 |
47 | def test_date_month(self):
48 | result = select(e for e in Entity1 if e.d.month == 10)
49 | self.assertEqual(len(result), 2)
50 |
51 | def test_date_day(self):
52 | result = select(e for e in Entity1 if e.d.day == 22)
53 | self.assertEqual(len(result), 1)
54 |
55 | def test_datetime_year(self):
56 | result = select(e for e in Entity1 if e.dt.year > 2009)
57 | self.assertEqual(len(result), 2)
58 |
59 | def test_datetime_month(self):
60 | result = select(e for e in Entity1 if e.dt.month == 10)
61 | self.assertEqual(len(result), 2)
62 |
63 | def test_datetime_day(self):
64 | result = select(e for e in Entity1 if e.dt.day == 22)
65 | self.assertEqual(len(result), 1)
66 |
67 | def test_datetime_hour(self):
68 | result = select(e for e in Entity1 if e.dt.hour == 10)
69 | self.assertEqual(len(result), 3)
70 |
71 | def test_datetime_minute(self):
72 | result = select(e for e in Entity1 if e.dt.minute == 20)
73 | self.assertEqual(len(result), 2)
74 |
75 | def test_datetime_second(self):
76 | result = select(e for e in Entity1 if e.dt.second == 30)
77 | self.assertEqual(len(result), 1)
78 |
79 | def test_date_sub_date(self):
80 | dt = date(2012, 1, 1)
81 | result = select(e.id for e in Entity1 if dt - e.d > timedelta(days=500))
82 | self.assertEqual(set(result), {1})
83 |
84 | def test_datetime_sub_datetime(self):
85 | dt = datetime(2012, 1, 1, 10, 20, 30)
86 | result = select(e.id for e in Entity1 if dt - e.dt > timedelta(days=500))
87 | self.assertEqual(set(result), {1})
88 |
89 | def test_date_sub_timedelta_param(self):
90 | td = timedelta(days=500)
91 | result = select(e.id for e in Entity1 if e.d - td < date(2009, 1, 1))
92 | self.assertEqual(set(result), {1})
93 |
94 | def test_date_sub_const_timedelta(self):
95 | result = select(e.id for e in Entity1 if e.d - timedelta(days=500) < date(2009, 1, 1))
96 | self.assertEqual(set(result), {1})
97 |
98 | def test_datetime_sub_timedelta_param(self):
99 | td = timedelta(days=500)
100 | result = select(e.id for e in Entity1 if e.dt - td < datetime(2009, 1, 1, 10, 20, 30))
101 | self.assertEqual(set(result), {1})
102 |
103 | def test_datetime_sub_const_timedelta(self):
104 | result = select(e.id for e in Entity1 if e.dt - timedelta(days=500) < datetime(2009, 1, 1, 10, 20, 30))
105 | self.assertEqual(set(result), {1})
106 |
107 | def test_date_add_timedelta_param(self):
108 | td = timedelta(days=500)
109 | result = select(e.id for e in Entity1 if e.d + td > date(2013, 1, 1))
110 | self.assertEqual(set(result), {3})
111 |
112 | def test_date_add_const_timedelta(self):
113 | result = select(e.id for e in Entity1 if e.d + timedelta(days=500) > date(2013, 1, 1))
114 | self.assertEqual(set(result), {3})
115 |
116 | def test_datetime_add_timedelta_param(self):
117 | td = timedelta(days=500)
118 | result = select(e.id for e in Entity1 if e.dt + td > date(2013, 1, 1))
119 | self.assertEqual(set(result), {3})
120 |
121 | def test_datetime_add_const_timedelta(self):
122 | result = select(e.id for e in Entity1 if e.dt + timedelta(days=500) > date(2013, 1, 1))
123 | self.assertEqual(set(result), {3})
124 |
125 | @raises_exception(TypeError, "Unsupported operand types 'date' and 'str' for operation '-' in expression: e.d - s")
126 | def test_date_sub_error(self):
127 | s = 'hello'
128 | result = select(e.id for e in Entity1 if e.d - s > timedelta(days=500))
129 | self.assertEqual(set(result), {1})
130 |
131 | @raises_exception(TypeError,
132 | "Unsupported operand types 'datetime' and 'str' for operation '-' in expression: e.dt - s")
133 | def test_datetime_sub_error(self):
134 | s = 'hello'
135 | result = select(e.id for e in Entity1 if e.dt - s > timedelta(days=500))
136 | self.assertEqual(set(result), {1})
137 |
138 |
139 | if __name__ == '__main__':
140 | unittest.main()
141 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_declarative_join_optimization.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from datetime import date
5 |
6 | from pony.orm.core import *
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import setup_database, teardown_database
9 |
10 | db = Database()
11 |
12 | class Department(db.Entity):
13 | name = Required(str)
14 | groups = Set('Group')
15 | courses = Set('Course')
16 |
17 | class Group(db.Entity):
18 | number = PrimaryKey(int)
19 | dept = Required(Department)
20 | major = Required(str)
21 | students = Set("Student")
22 |
23 | class Course(db.Entity):
24 | name = Required(str)
25 | dept = Required(Department)
26 | semester = Required(int)
27 | credits = Required(int)
28 | students = Set("Student")
29 | PrimaryKey(name, semester)
30 |
31 | class Student(db.Entity):
32 | id = PrimaryKey(int, auto=True)
33 | name = Required(str)
34 | dob = Required(date)
35 | picture = Optional(buffer)
36 | gpa = Required(float, default=0)
37 | group = Required(Group)
38 | courses = Set(Course)
39 |
40 |
41 | class TestM2MOptimization(unittest.TestCase):
42 | @classmethod
43 | def setUpClass(cls):
44 | setup_database(db)
45 | @classmethod
46 | def tearDownClass(cls):
47 | teardown_database(db)
48 | def setUp(self):
49 | rollback()
50 | db_session.__enter__()
51 | def tearDown(self):
52 | rollback()
53 | db_session.__exit__()
54 | def test1(self):
55 | q = select(s for s in Student if len(s.courses) > 2)
56 | self.assertEqual(Course._table_ not in flatten(q._translator.conditions), True)
57 | def test2(self):
58 | q = select(s for s in Student if max(s.courses.semester) > 2)
59 | self.assertEqual(Course._table_ not in flatten(q._translator.conditions), True)
60 | # def test3(self):
61 | # q = select(s for s in Student if max(s.courses.credits) > 2)
62 | # self.assertEqual(Course._table_ in flatten(q._translator.conditions), True)
63 | # self.assertEqual(Course.students.table in flatten(q._translator.conditions), True)
64 | def test4(self):
65 | q = select(g for g in Group if sum(g.students.gpa) > 5)
66 | self.assertEqual(Group._table_ not in flatten(q._translator.conditions), True)
67 | def test5(self):
68 | q = select(s for s in Student if s.group.number == 1 or s.group.major == '1')
69 | self.assertEqual(Group._table_ in flatten(q._translator.sqlquery.from_ast), True)
70 | # def test6(self): ### Broken with ExprEvalError: Group[101] raises ObjectNotFound: Group[101]
71 | # q = select(s for s in Student if s.group == Group[101])
72 | # self.assertEqual(Group._table_ not in flatten(q._translator.sqlquery.from_ast), True)
73 | def test7(self):
74 | q = select(s for s in Student if sum(c.credits for c in Course if s.group.dept == c.dept) > 10)
75 | objects = q[:]
76 | student_table_name = 'Student'
77 | group_table_name = 'Group'
78 | if not (db.provider.dialect == 'SQLite' and pony.__version__ < '0.9'):
79 | student_table_name = student_table_name.lower()
80 | group_table_name = group_table_name.lower()
81 | self.assertEqual(q._translator.sqlquery.from_ast, [
82 | 'FROM', ['s', 'TABLE', student_table_name],
83 | ['group', 'TABLE', group_table_name,
84 | ['EQ', ['COLUMN', 's', 'group'], ['COLUMN', 'group', 'number']]
85 | ]
86 | ])
87 |
88 |
89 | if __name__ == '__main__':
90 | unittest.main()
91 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_declarative_object_flat_monad.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from pony.orm.core import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 | class Student(db.Entity):
10 | name = Required(str)
11 | scholarship = Optional(int)
12 | group = Required("Group")
13 | marks = Set("Mark")
14 |
15 | class Group(db.Entity):
16 | number = PrimaryKey(int)
17 | department = Required(int)
18 | students = Set(Student)
19 | subjects = Set("Subject")
20 |
21 | class Subject(db.Entity):
22 | name = PrimaryKey(str)
23 | groups = Set(Group)
24 | marks = Set("Mark")
25 |
26 | class Mark(db.Entity):
27 | value = Required(int)
28 | student = Required(Student)
29 | subject = Required(Subject)
30 | PrimaryKey(student, subject)
31 |
32 |
33 | class TestObjectFlatMonad(unittest.TestCase):
34 | @classmethod
35 | def setUpClass(self):
36 | setup_database(db)
37 | with db_session:
38 | Math = Subject(name="Math")
39 | Physics = Subject(name="Physics")
40 | History = Subject(name="History")
41 |
42 | g41 = Group(number=41, department=101, subjects=[Math, Physics, History])
43 | g42 = Group(number=42, department=102, subjects=[Math, Physics])
44 | g43 = Group(number=43, department=102, subjects=[Physics])
45 |
46 | s1 = Student(id=1, name="Joe", scholarship=None, group=g41)
47 | s2 = Student(id=2, name="Bob", scholarship=100, group=g41)
48 | s3 = Student(id=3, name="Beth", scholarship=500, group=g41)
49 | s4 = Student(id=4, name="Jon", scholarship=500, group=g42)
50 | s5 = Student(id=5, name="Pete", scholarship=700, group=g42)
51 |
52 | Mark(value=5, student=s1, subject=Math)
53 | Mark(value=4, student=s2, subject=Physics)
54 | Mark(value=3, student=s2, subject=Math)
55 | Mark(value=2, student=s2, subject=History)
56 | Mark(value=1, student=s3, subject=History)
57 | Mark(value=2, student=s3, subject=Math)
58 | Mark(value=2, student=s4, subject=Math)
59 |
60 | @classmethod
61 | def tearDownClass(cls):
62 | teardown_database(db)
63 |
64 | @db_session
65 | def test1(self):
66 | result = set(select(s.groups for s in Subject if len(s.name) == 4))
67 | self.assertEqual(result, {Group[41], Group[42]})
68 |
69 | @db_session
70 | def test2(self):
71 | result = set(select(g.students for g in Group if g.department == 102))
72 | self.assertEqual(result, {Student[5], Student[4]})
73 |
74 | if __name__ == '__main__':
75 | unittest.main()
76 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_deduplication.py:
--------------------------------------------------------------------------------
1 | from io import StringIO
2 |
3 | from pony.orm import *
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 | import unittest
7 |
8 | db = Database()
9 |
10 | class A(db.Entity):
11 | id = PrimaryKey(int)
12 | x = Required(bool)
13 | y = Required(float)
14 |
15 |
16 | class TestDeduplication(unittest.TestCase):
17 | @classmethod
18 | def setUpClass(cls):
19 | setup_database(db)
20 | with db_session:
21 | a1 = A(id=1, x=False, y=3.0)
22 | a2 = A(id=2, x=True, y=4.0)
23 | a3 = A(id=3, x=False, y=1.0)
24 |
25 | @classmethod
26 | def tearDownClass(cls):
27 | teardown_database(db)
28 |
29 | @db_session
30 | def test_1(self):
31 | a2 = A.get(id=2)
32 | a1 = A.get(id=1)
33 | self.assertIs(a1.id, 1)
34 |
35 | @db_session
36 | def test_2(self):
37 | a3 = A.get(id=3)
38 | a1 = A.get(id=1)
39 | self.assertIs(a1.id, 1)
40 |
41 | @db_session
42 | def test_3(self):
43 | q = A.select().order_by(-1)
44 | stream = StringIO()
45 | q.show(stream=stream)
46 | s = stream.getvalue()
47 | self.assertEqual(s, 'id|x |y \n'
48 | '--+-----+---\n'
49 | '3 |False|1.0\n'
50 | '2 |True |4.0\n'
51 | '1 |False|3.0\n')
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_distinct.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 | db = Database()
10 |
11 | class Department(db.Entity):
12 | number = PrimaryKey(int)
13 | groups = Set('Group')
14 |
15 | class Group(db.Entity):
16 | id = PrimaryKey(int)
17 | dept = Required('Department')
18 | students = Set('Student')
19 |
20 | class Student(db.Entity):
21 | name = Required(str)
22 | age = Required(int)
23 | group = Required('Group')
24 | scholarship = Required(int, default=0)
25 | courses = Set('Course')
26 |
27 | class Course(db.Entity):
28 | name = Required(str)
29 | semester = Required(int)
30 | PrimaryKey(name, semester)
31 | students = Set('Student')
32 |
33 |
34 | class TestDistinct(unittest.TestCase):
35 | @classmethod
36 | def setUpClass(cls):
37 | setup_database(db)
38 | with db_session:
39 | d1 = Department(number=1)
40 | d2 = Department(number=2)
41 | g1 = Group(id=1, dept=d1)
42 | g2 = Group(id=2, dept=d2)
43 | s1 = Student(id=1, name='S1', age=20, group=g1, scholarship=0)
44 | s2 = Student(id=2, name='S2', age=21, group=g1, scholarship=100)
45 | s3 = Student(id=3, name='S3', age=23, group=g1, scholarship=200)
46 | s4 = Student(id=4, name='S4', age=21, group=g1, scholarship=100)
47 | s5 = Student(id=5, name='S5', age=23, group=g2, scholarship=0)
48 | s6 = Student(id=6, name='S6', age=23, group=g2, scholarship=200)
49 | c1 = Course(name='C1', semester=1, students=[s1, s2, s3])
50 | c2 = Course(name='C2', semester=1, students=[s2, s3, s5, s6])
51 | c3 = Course(name='C3', semester=2, students=[s4, s5, s6])
52 |
53 | @classmethod
54 | def tearDownClass(cls):
55 | teardown_database(db)
56 |
57 | def setUp(self):
58 | db_session.__enter__()
59 |
60 | def tearDown(self):
61 | db_session.__exit__()
62 |
63 | def test_group_by(self):
64 | result = set(select((s.age, sum(s.scholarship)) for s in Student if s.scholarship > 0))
65 | self.assertEqual(result, {(21, 200), (23, 400)})
66 | self.assertNotIn('distinct', db.last_sql.lower())
67 |
68 | def test_group_by_having(self):
69 | result = set(select((s.age, sum(s.scholarship)) for s in Student if sum(s.scholarship) < 300))
70 | self.assertEqual(result, {(20, 0), (21, 200)})
71 | self.assertNotIn('distinct', db.last_sql.lower())
72 |
73 | def test_aggregation_no_group_by_1(self):
74 | result = set(select(sum(s.scholarship) for s in Student if s.age < 23))
75 | self.assertEqual(result, {200})
76 | self.assertNotIn('distinct', db.last_sql.lower())
77 |
78 | def test_aggregation_no_group_by_2(self):
79 | result = set(select((sum(s.scholarship), min(s.scholarship)) for s in Student if s.age < 23))
80 | self.assertEqual(result, {(200, 0)})
81 | self.assertNotIn('distinct', db.last_sql.lower())
82 |
83 | def test_aggregation_no_group_by_3(self):
84 | result = set(select((sum(s.scholarship), min(s.scholarship))
85 | for s in Student for g in Group
86 | if s.group == g and g.dept.number == 1))
87 | self.assertEqual(result, {(400, 0)})
88 | self.assertNotIn('distinct', db.last_sql.lower())
89 |
90 |
91 | if __name__ == "__main__":
92 | unittest.main()
93 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_entity_init.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from datetime import date, datetime
5 | from hashlib import md5
6 |
7 | from pony.orm.tests.testutils import raises_exception
8 | from pony.orm import *
9 | from pony.orm.tests import setup_database, teardown_database
10 |
11 | db = Database()
12 |
13 |
14 | class User(db.Entity):
15 | name = Required(str)
16 | password = Required(str)
17 | created_at = Required(datetime)
18 |
19 | def __init__(self, name, password):
20 | password = md5(password.encode('utf8')).hexdigest()
21 | super(User, self).__init__(name=name, password=password, created_at=datetime.now())
22 | self.uppercase_name = name.upper()
23 |
24 |
25 | class TestCustomInit(unittest.TestCase):
26 | @classmethod
27 | def setUpClass(cls):
28 | setup_database(db)
29 |
30 | @classmethod
31 | def tearDownClass(self):
32 | teardown_database(db)
33 |
34 | def test1(self):
35 | with db_session:
36 | u1 = User('John', '123')
37 | u2 = User('Mike', '456')
38 | commit()
39 | self.assertEqual(u1.name, 'John')
40 | self.assertEqual(u1.uppercase_name, 'JOHN')
41 | self.assertEqual(u1.password, md5(b'123').hexdigest())
42 | self.assertEqual(u2.name, 'Mike')
43 | self.assertEqual(u2.uppercase_name, 'MIKE')
44 | self.assertEqual(u2.password, md5(b'456').hexdigest())
45 |
46 | with db_session:
47 | users = select(u for u in User).order_by(User.id)
48 | self.assertEqual(len(users), 2)
49 | u1, u2 = users
50 | self.assertEqual(u1.name, 'John')
51 | self.assertTrue(not hasattr(u1, 'uppercase_name'))
52 | self.assertEqual(u1.password, md5(b'123').hexdigest())
53 | self.assertEqual(u2.name, 'Mike')
54 | self.assertTrue(not hasattr(u2, 'uppercase_name'))
55 | self.assertEqual(u2.password, md5(b'456').hexdigest())
56 |
57 | if __name__ == '__main__':
58 | unittest.main()
--------------------------------------------------------------------------------
/pony/orm/tests/test_entity_proxy.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests.testutils import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 | class Country(db.Entity):
10 | id = PrimaryKey(int)
11 | name = Required(str)
12 | persons = Set("Person")
13 |
14 | class Person(db.Entity):
15 | id = PrimaryKey(int)
16 | name = Required(str)
17 | country = Required(Country)
18 |
19 | class TestProxy(unittest.TestCase):
20 | def setUp(self):
21 | setup_database(db)
22 | with db_session:
23 | c1 = Country(id=1, name='Russia')
24 | c2 = Country(id=2, name='Japan')
25 | Person(id=1, name='Alexander Nevskiy', country=c1)
26 | Person(id=2, name='Raikou Minamoto', country=c2)
27 | Person(id=3, name='Ibaraki Douji', country=c2)
28 |
29 | def tearDown(self):
30 | teardown_database(db)
31 |
32 | def test_1(self):
33 | with db_session:
34 | p = make_proxy(Person[2])
35 |
36 | with db_session:
37 | x1 = db.local_stats[None].db_count # number of queries
38 | # it is possible to access p attributes in a new db_session
39 | name = p.name
40 | country = p.country
41 | x2 = db.local_stats[None].db_count
42 |
43 | # p.name and p.country are loaded with a single query
44 | self.assertEqual(x1, x2-1)
45 |
46 | def test_2(self):
47 | with db_session:
48 | p = make_proxy(Person[2])
49 | name = p.name
50 | country = p.country
51 |
52 | with db_session:
53 | x1 = db.local_stats[None].db_count
54 | name = p.name
55 | country = p.country
56 | x2 = db.local_stats[None].db_count
57 |
58 | # attribute values from the first db_session should be ignored and loaded again
59 | self.assertEqual(x1, x2-1)
60 |
61 | def test_3(self):
62 | with db_session:
63 | p = Person[2]
64 | proxy = make_proxy(p)
65 |
66 | with db_session:
67 | p2 = Person[2]
68 | name1 = 'Tamamo no Mae'
69 | # It is possible to assign new attribute values to a proxy object
70 | p2.name = name1
71 | name2 = proxy.name
72 |
73 | self.assertEqual(name1, name2)
74 |
75 |
76 | def test_4(self):
77 | with db_session:
78 | p = Person[2]
79 | proxy = make_proxy(p)
80 |
81 | with db_session:
82 | p2 = Person[2]
83 | name1 = 'Tamamo no Mae'
84 | p2.name = name1
85 |
86 | with db_session:
87 | # new attribute value was successfully stored in the database
88 | name2 = proxy.name
89 |
90 | self.assertEqual(name1, name2)
91 |
92 | def test_5(self):
93 | with db_session:
94 | p = Person[2]
95 | r = repr(p)
96 | self.assertEqual(r, 'Person[2]')
97 |
98 | proxy = make_proxy(p)
99 | r = repr(proxy)
100 | # proxy object has specific repr
101 | self.assertEqual(r, '')
102 |
103 | r = repr(proxy)
104 | # repr of proxy object can be used outside of db_session
105 | self.assertEqual(r, '')
106 |
107 | del p
108 | r = repr(proxy)
109 | # repr works even if the original object was deleted
110 | self.assertEqual(r, '')
111 |
112 |
113 | def test_6(self):
114 | with db_session:
115 | p = Person[2]
116 | proxy = make_proxy(p)
117 | proxy.name = 'Okita Souji'
118 | # after assignment, the attribute value is the same for the proxy and for the original object
119 | self.assertEqual(proxy.name, 'Okita Souji')
120 | self.assertEqual(p.name, 'Okita Souji')
121 |
122 |
123 | def test_7(self):
124 | with db_session:
125 | p = Person[2]
126 | proxy = make_proxy(p)
127 | proxy.name = 'Okita Souji'
128 | # after assignment, the attribute value is the same for the proxy and for the original object
129 | self.assertEqual(proxy.name, 'Okita Souji')
130 | self.assertEqual(p.name, 'Okita Souji')
131 |
132 |
133 | def test_8(self):
134 | with db_session:
135 | c1 = Country[1]
136 | c1_proxy = make_proxy(c1)
137 | p2 = Person[2]
138 | self.assertNotEqual(p2.country, c1)
139 | self.assertNotEqual(p2.country, c1_proxy)
140 | # proxy can be used in attribute assignment
141 | p2.country = c1_proxy
142 | self.assertEqual(p2.country, c1_proxy)
143 | self.assertIs(p2.country, c1)
144 |
145 |
146 | def test_9(self):
147 | with db_session:
148 | c2 = Country[2]
149 | c2_proxy = make_proxy(c2)
150 | persons = select(p for p in Person if p.country == c2_proxy)
151 | self.assertEqual({p.id for p in persons}, {2, 3})
152 |
153 | if __name__ == '__main__':
154 | unittest.main()
155 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_exists.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm.core import *
4 | from pony.orm.tests.testutils import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 | class Group(db.Entity):
10 | students = Set('Student')
11 |
12 | class Student(db.Entity):
13 | first_name = Required(str)
14 | last_name = Required(str)
15 | login = Optional(str, nullable=True)
16 | graduated = Optional(bool, default=False)
17 | group = Required(Group)
18 | passport = Optional('Passport', column='passport')
19 |
20 | class Passport(db.Entity):
21 | student = Optional(Student)
22 |
23 |
24 | class TestExists(unittest.TestCase):
25 | @classmethod
26 | def setUpClass(cls):
27 | setup_database(db)
28 | with db_session:
29 | g1 = Group(id=1)
30 | g2 = Group(id=2)
31 |
32 | p = Passport(id=1)
33 |
34 | Student(id=1, first_name='Mashu', last_name='Kyrielight', login='Shielder', group=g1)
35 | Student(id=2, first_name='Okita', last_name='Souji', login='Sakura', group=g1)
36 | Student(id=3, first_name='Francis', last_name='Drake', group=g2, graduated=True)
37 | Student(id=4, first_name='Oda', last_name='Nobunaga', group=g2, graduated=True)
38 | Student(id=5, first_name='William', last_name='Shakespeare', group=g2, graduated=True, passport=p)
39 |
40 | @classmethod
41 | def tearDownClass(cls):
42 | teardown_database(db)
43 |
44 | def setUp(self):
45 | rollback()
46 | db_session.__enter__()
47 |
48 | def tearDown(self):
49 | rollback()
50 | db_session.__exit__()
51 |
52 | def test_1(self):
53 | q = select(g for g in Group if exists(s.login for s in g.students))[:]
54 | self.assertEqual(q[0], Group[1])
55 |
56 | def test_2(self):
57 | q = select(g for g in Group if exists(s.graduated for s in g.students))[:]
58 | self.assertEqual(q[0], Group[2])
59 |
60 | def test_3(self):
61 | q = select(s for s in Student if
62 | exists(len(s2.first_name) == len(s.first_name) and s != s2 for s2 in Student))[:]
63 | self.assertEqual(set(q), {Student[1], Student[2], Student[3], Student[5]})
64 |
65 | def test_4(self):
66 | q = select(g for g in Group if not exists(not s.graduated for s in g.students))[:]
67 | self.assertEqual(q[0], Group[2])
68 |
69 | def test_5(self):
70 | q = select(g for g in Group if exists(s for s in g.students))[:]
71 | self.assertEqual(set(q), {Group[1], Group[2]})
72 |
73 | def test_6(self):
74 | q = select(g for g in Group if exists(s.login for s in g.students if s.first_name != 'Okita') and g.id != 10)[:]
75 | self.assertEqual(q[0], Group[1])
76 |
77 | def test_7(self):
78 | q = select(g for g in Group if exists(s.passport for s in g.students))[:]
79 | self.assertEqual(q[0], Group[2])
--------------------------------------------------------------------------------
/pony/orm/tests/test_f_strings.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from pony.orm.core import *
3 | from pony.orm.tests.testutils import *
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 |
7 | db = Database()
8 |
9 | class Person(db.Entity):
10 | first_name = Required(str)
11 | last_name = Required(str)
12 | age = Optional(int)
13 | value = Required(float)
14 |
15 |
16 | class TestFString(unittest.TestCase):
17 | @classmethod
18 | def setUpClass(cls):
19 | setup_database(db)
20 | with db_session:
21 | Person(id=1, first_name='Alexander', last_name='Tischenko', age=23, value=1.4)
22 | Person(id=2, first_name='Alexander', last_name='Kozlovskiy', age=42, value=1.2)
23 | Person(id=3, first_name='Arthur', last_name='Pendragon', age=54, value=1.33)
24 | Person(id=4, first_name='Okita', last_name='Souji', age=15, value=2.1)
25 | Person(id=5, first_name='Musashi', last_name='Miyamoto', age=None, value=0.9)
26 | Person(id=6, first_name='Jeanne', last_name="d'Arc", age=30, value=43.212)
27 |
28 | @classmethod
29 | def tearDownClass(cls):
30 | teardown_database(db)
31 |
32 | def setUp(self):
33 | rollback()
34 | db_session.__enter__()
35 | def tearDown(self):
36 | rollback()
37 | db_session.__exit__()
38 |
39 | def test_1(self):
40 | x = 'Alexander'
41 | y = 'Tischenko'
42 |
43 | q = select(p.id for p in Person if p.first_name + ' ' + p.last_name == f'{x} {y}')
44 | self.assertEqual(set(q), {1})
45 |
46 | q2 = select("""p.id for p in Person if p.first_name + ' ' + p.last_name == f'{x} {y}'""")
47 | self.assertEqual(set(q2), {1})
48 |
49 | def test_2(self):
50 | q = select(p.id for p in Person if f'{p.first_name} {p.last_name}' == 'Alexander Tischenko')
51 | self.assertEqual(set(q), {1})
52 |
53 | q2 = select("""p.id for p in Person if f'{p.first_name} {p.last_name}' == 'Alexander Tischenko'""")
54 | self.assertEqual(set(q2), {1})
55 |
56 | def test_3(self):
57 | x = 'Great'
58 |
59 | q = select(f'{p.first_name!s} the {x}' for p in Person if p.id == 1)
60 | self.assertEqual(set(q), {'Alexander the Great'})
61 |
62 | q2 = select("""f'{p.first_name!s} the {x}' for p in Person if p.id == 1""")
63 | self.assertEqual(set(q2), {'Alexander the Great'})
64 |
65 | def test_4(self):
66 | q = select(f'{p.first_name} {p.age}' for p in Person if p.id == 1)
67 | self.assertEqual(set(q), {'Alexander 23'})
68 |
69 | q2 = select("""f'{p.first_name} {p.age}' for p in Person if p.id == 1""")
70 | self.assertEqual(set(q2), {'Alexander 23'})
71 |
72 | def test_5(self):
73 | q = select(f'{p.first_name} {p.age}' for p in Person if p.id == 1)
74 | self.assertEqual(set(q), {'Alexander 23'})
75 |
76 | q2 = select("""f'{p.first_name} {p.age}' for p in Person if p.id == 1""")
77 | self.assertEqual(set(q2), {'Alexander 23'})
78 |
79 | @raises_exception(NotImplementedError, 'You cannot set width and precision for f-string expression in query')
80 | def test_6a(self):
81 | width = 3
82 | precision = 4
83 | q = select(p.id for p in Person if f'{p.value:{width}.{precision}}')[:]
84 |
85 | @raises_exception(NotImplementedError, 'You cannot set width and precision for f-string expression in query')
86 | def test_6b(self):
87 | width = 3
88 | precision = 4
89 | q = select("""p.id for p in Person if f'{p.value:{width}.{precision}}'""")[:]
90 | q.show()
91 |
92 | @raises_exception(NotImplementedError, 'You cannot specify conversion type for f-string expression in query')
93 | def test_7a(self):
94 | width = 3
95 | precision = 4
96 | q = select(p.id for p in Person if f'{p.value!r}')[:]
97 |
98 | @raises_exception(NotImplementedError, 'You cannot specify conversion type for f-string expression in query')
99 | def test_7b(self):
100 | width = 3
101 | precision = 4
102 | q = select("""p.id for p in Person if f'{p.value!r}'""")[:]
103 | q.show()
104 |
105 | def test_8(self):
106 | x = 'Tischenko'
107 | q = select(p.first_name + f"{' ' + x}" for p in Person if p.id == 1)
108 | self.assertEqual(set(q), {'Alexander Tischenko'})
109 |
110 | q2 = select("""p.first_name + f"{' ' + x}" for p in Person if p.id == 1""")
111 | self.assertEqual(set(q2), {'Alexander Tischenko'})
112 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_filter.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.tests.model1 import *
6 | from pony.orm.tests import setup_database, teardown_database
7 |
8 |
9 | class TestFilter(unittest.TestCase):
10 | @classmethod
11 | def setUpClass(cls):
12 | setup_database(db)
13 | populate_db()
14 | @classmethod
15 | def tearDownClass(cls):
16 | teardown_database(db)
17 | def setUp(self):
18 | rollback()
19 | db_session.__enter__()
20 | def tearDown(self):
21 | rollback()
22 | db_session.__exit__()
23 | def test_filter_1(self):
24 | q = select(s for s in Student)
25 | result = set(q.filter(scholarship=0))
26 | self.assertEqual(result, {Student[101], Student[103]})
27 | def test_filter_2(self):
28 | q = select(s for s in Student)
29 | q2 = q.filter(scholarship=500)
30 | result = set(q2.filter(group=Group['3132']))
31 | self.assertEqual(result, {Student[104]})
32 | def test_filter_3(self):
33 | q = select(s for s in Student)
34 | q2 = q.filter(lambda s: s.scholarship > 500)
35 | result = set(q2.filter(lambda s: count(s.marks) > 0))
36 | self.assertEqual(result, {Student[102]})
37 | def test_filter_4(self):
38 | q = select(s for s in Student)
39 | q2 = q.filter(lambda s: s.scholarship != 500)
40 | q3 = q2.order_by(1)
41 | result = list(q3.filter(lambda s: count(s.marks) > 1))
42 | self.assertEqual(result, [Student[101], Student[103]])
43 | def test_filter_5(self):
44 | q = select(s for s in Student)
45 | q2 = q.filter(lambda s: s.scholarship != 500)
46 | q3 = q2.order_by(Student.name)
47 | result = list(q3.filter(lambda s: count(s.marks) > 1))
48 | self.assertEqual(result, [Student[103], Student[101]])
49 | def test_filter_6(self):
50 | q = select(s for s in Student)
51 | q2 = q.filter(lambda s: s.scholarship != 500)
52 | q3 = q2.order_by(lambda s: s.name)
53 | result = list(q3.filter(lambda s: count(s.marks) > 1))
54 | self.assertEqual(result, [Student[103], Student[101]])
55 | def test_filter_7(self):
56 | q = select(s for s in Student)
57 | q2 = q.filter(scholarship=0)
58 | result = set(q2.filter(lambda s: count(s.marks) > 1))
59 | self.assertEqual(result, {Student[103], Student[101]})
60 | def test_filter_8(self):
61 | q = select(s for s in Student)
62 | q2 = q.filter(lambda s: s.scholarship != 500)
63 | q3 = q2.order_by(lambda s: s.name)
64 | q4 = q3.order_by(None)
65 | result = set(q4.filter(lambda s: count(s.marks) > 1))
66 | self.assertEqual(result, {Student[103], Student[101]})
67 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_flush.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 | db = Database()
10 |
11 |
12 | class Person(db.Entity):
13 | name = Required(str)
14 |
15 |
16 | class TestFlush(unittest.TestCase):
17 | @classmethod
18 | def setUpClass(cls):
19 | setup_database(db)
20 |
21 | @classmethod
22 | def tearDownClass(self):
23 | teardown_database(db)
24 |
25 | def test1(self):
26 | with db_session:
27 | a = Person(name='A')
28 | b = Person(name='B')
29 | c = Person(name='C')
30 | self.assertEqual(a.id, None)
31 | self.assertEqual(b.id, None)
32 | self.assertEqual(c.id, None)
33 |
34 | b.flush()
35 | self.assertEqual(a.id, None)
36 | self.assertIsNotNone(b.id)
37 | b_id = b.id
38 | self.assertEqual(c.id, None)
39 |
40 | flush()
41 | self.assertIsNotNone(a.id)
42 | self.assertEqual(b.id, b_id)
43 | self.assertIsNotNone(c.id)
44 | self.assertEqual(len({a.id, b.id, c.id}), 3)
45 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_generator_db_session.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.core import local
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import setup_database, teardown_database
9 |
10 |
11 | class TestGeneratorDbSession(unittest.TestCase):
12 | def setUp(self):
13 | db = Database()
14 | class Account(db.Entity):
15 | id = PrimaryKey(int)
16 | amount = Required(int)
17 | setup_database(db)
18 |
19 | self.db = db
20 | self.Account = Account
21 |
22 | with db_session:
23 | a1 = Account(id=1, amount=1000)
24 | a2 = Account(id=2, amount=2000)
25 | a3 = Account(id=3, amount=3000)
26 |
27 | def tearDown(self):
28 | teardown_database(self.db)
29 | assert local.db_session is None
30 | self.db = self.Account = None
31 |
32 | @raises_exception(TypeError, 'db_session with `retry` option cannot be applied to generator function')
33 | def test1(self):
34 | @db_session(retry=3)
35 | def f(): yield
36 |
37 | @raises_exception(TypeError, 'db_session with `ddl` option cannot be applied to generator function')
38 | def test2(self):
39 | @db_session(ddl=True)
40 | def f(): yield
41 |
42 | @raises_exception(TypeError, 'db_session with `serializable` option cannot be applied to generator function')
43 | def test3(self):
44 | @db_session(serializable=True)
45 | def f(): yield
46 |
47 | def test4(self):
48 | @db_session(immediate=True)
49 | def f(): yield
50 |
51 | @raises_exception(TransactionError, '@db_session-wrapped generator cannot be used inside another db_session')
52 | def test5(self):
53 | @db_session
54 | def f(): yield
55 | with db_session:
56 | next(f())
57 |
58 | def test6(self):
59 | @db_session
60 | def f():
61 | x = local.db_session
62 | self.assertTrue(x is not None)
63 |
64 | yield self.db._get_cache()
65 | self.assertEqual(local.db_session, x)
66 |
67 | a1 = self.Account[1]
68 | yield a1.amount
69 | self.assertEqual(local.db_session, x)
70 |
71 | a2 = self.Account[2]
72 | yield a2.amount
73 |
74 | gen = f()
75 | cache = next(gen)
76 | self.assertTrue(cache.is_alive)
77 | self.assertEqual(local.db_session, None)
78 |
79 | amount = next(gen)
80 | self.assertEqual(amount, 1000)
81 | self.assertEqual(local.db_session, None)
82 |
83 | amount = next(gen)
84 | self.assertEqual(amount, 2000)
85 | self.assertEqual(local.db_session, None)
86 |
87 | try: next(gen)
88 | except StopIteration:
89 | self.assertFalse(cache.is_alive)
90 | else:
91 | self.fail()
92 |
93 | def test7(self):
94 | @db_session
95 | def f(id1):
96 | a1 = self.Account[id1]
97 | id2 = yield a1.amount
98 | a2 = self.Account[id2]
99 | amount = yield a2.amount
100 | a1.amount -= amount
101 | a2.amount += amount
102 | commit()
103 |
104 | gen = f(1)
105 |
106 | amount1 = next(gen)
107 | self.assertEqual(amount1, 1000)
108 |
109 | amount2 = gen.send(2)
110 | self.assertEqual(amount2, 2000)
111 |
112 | try:
113 | gen.send(100)
114 | except StopIteration:
115 | pass
116 | else:
117 | self.fail()
118 |
119 | with db_session:
120 | a1 = self.Account[1]
121 | self.assertEqual(a1.amount, 900)
122 | a2 = self.Account[2]
123 | self.assertEqual(a2.amount, 2100)
124 |
125 | @raises_exception(TransactionError, 'You need to manually commit() changes before suspending the generator')
126 | def test8(self):
127 | @db_session
128 | def f(id1):
129 | a1 = self.Account[id1]
130 | a1.amount += 100
131 | yield a1.amount
132 |
133 | for amount in f(1):
134 | pass
135 |
136 | def test9(self):
137 | @db_session
138 | def f(id1):
139 | a1 = self.Account[id1]
140 | a1.amount += 100
141 | commit()
142 | yield a1.amount
143 |
144 | for amount in f(1):
145 | pass
146 |
147 | def test10(self):
148 | @db_session
149 | def f(id1):
150 | a1 = self.Account[id1]
151 | yield a1.amount
152 | a1.amount += 100
153 |
154 | with db_session:
155 | a = self.Account[1].amount
156 | for amount in f(1):
157 | pass
158 | with db_session:
159 | b = self.Account[1].amount
160 |
161 | self.assertEqual(b, a + 100)
162 |
163 | def test12(self):
164 | @db_session
165 | def f(id1):
166 | a1 = self.Account[id1]
167 | yield a1.amount
168 |
169 | gen = f(1)
170 | next(gen)
171 | gen.close()
172 |
173 | @raises_exception(TypeError, 'error message')
174 | def test13(self):
175 | @db_session
176 | def f(id1):
177 | a1 = self.Account[id1]
178 | yield a1.amount
179 |
180 | gen = f(1)
181 | next(gen)
182 | gen.throw(TypeError('error message'))
183 |
184 | if __name__ == '__main__':
185 | unittest.main()
186 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_get_pk.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from datetime import date
3 |
4 | from pony.orm import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | day = date.today()
8 |
9 | db = Database()
10 |
11 | class A(db.Entity):
12 | b = Required("B")
13 | c = Required("C")
14 | PrimaryKey(b, c)
15 |
16 | class B(db.Entity):
17 | id = PrimaryKey(date)
18 | a_set = Set(A)
19 |
20 | class C(db.Entity):
21 | x = Required("X")
22 | y = Required("Y")
23 | a_set = Set(A)
24 | PrimaryKey(x, y)
25 |
26 | class X(db.Entity):
27 | id = PrimaryKey(int)
28 | c_set = Set(C)
29 |
30 | class Y(db.Entity):
31 | id = PrimaryKey(int)
32 | c_set = Set(C)
33 |
34 |
35 | class Test(unittest.TestCase):
36 | def setUp(self):
37 | setup_database(db)
38 | with db_session:
39 | x1 = X(id=123)
40 | y1 = Y(id=456)
41 | b1 = B(id=day)
42 | c1 = C(x=x1, y=y1)
43 | A(b=b1, c=c1)
44 |
45 | def tearDown(self):
46 | teardown_database(db)
47 |
48 | @db_session
49 | def test_1(self):
50 | a1 = A.select().first()
51 | a2 = A[a1.get_pk()]
52 | self.assertEqual(a1, a2)
53 |
54 | @db_session
55 | def test2(self):
56 | a = A.select().first()
57 | b = B.select().first()
58 | c = C.select().first()
59 | pk = (b.get_pk(), c._get_raw_pkval_())
60 | self.assertTrue(a is A[pk])
61 |
62 | @db_session
63 | def test3(self):
64 | a = A.select().first()
65 | c = C.select().first()
66 | pk = (day, c.get_pk())
67 | self.assertTrue(a is A[pk])
68 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_getattr.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony import orm
5 | from pony.utils import cached_property
6 | from pony.orm.tests.testutils import raises_exception
7 | from pony.orm.tests import db_params, setup_database, teardown_database
8 |
9 | class Test(unittest.TestCase):
10 |
11 | @cached_property
12 | def db(self):
13 | return orm.Database()
14 |
15 | def setUp(self):
16 | db = self.db
17 |
18 | class Genre(db.Entity):
19 | name = orm.Required(str)
20 | artists = orm.Set('Artist')
21 |
22 | class Hobby(db.Entity):
23 | name = orm.Required(str)
24 | artists = orm.Set('Artist')
25 |
26 | class Artist(db.Entity):
27 | name = orm.Required(str)
28 | age = orm.Optional(int)
29 | hobbies = orm.Set(Hobby)
30 | genres = orm.Set(Genre)
31 |
32 | setup_database(db)
33 |
34 | with orm.db_session:
35 | pop = Genre(name='Pop')
36 | Artist(name='Sia', age=40, genres=[pop])
37 | Hobby(name='Swimming')
38 |
39 | pony.options.INNER_JOIN_SYNTAX = True
40 |
41 | def tearDown(self):
42 | teardown_database(self.db)
43 |
44 | @db_session
45 | def test_no_caching(self):
46 | for attr_name, attr_type in zip(['name', 'age'], [str, int]):
47 | val = select(getattr(x, attr_name) for x in self.db.Artist).first()
48 | self.assertIsInstance(val, attr_type)
49 |
50 | @db_session
51 | def test_simple(self):
52 | val = select(getattr(x, 'age') for x in self.db.Artist).first()
53 | self.assertIsInstance(val, int)
54 |
55 | @db_session
56 | def test_expr(self):
57 | val = select(getattr(x, ''.join(['ag', 'e'])) for x in self.db.Artist).first()
58 | self.assertIsInstance(val, int)
59 |
60 | @db_session
61 | def test_external(self):
62 | class data:
63 | id = 1
64 | val = select(x.id for x in self.db.Artist if x.id >= getattr(data, 'id')).first()
65 | self.assertIsNotNone(val)
66 |
67 | @db_session
68 | def test_related(self):
69 | val = select(getattr(x.genres, 'name') for x in self.db.Artist).first()
70 | self.assertIsNotNone(val)
71 |
72 | @db_session
73 | def test_not_instance_iter(self):
74 | val = select(getattr(x.name, 'startswith')('S') for x in self.db.Artist).first()
75 | self.assertTrue(val)
76 |
77 | @raises_exception(TranslationError, 'Expression `getattr(x, x.name)` cannot be translated into SQL '
78 | 'because x.name will be different for each row')
79 | @db_session
80 | def test_not_external(self):
81 | select(getattr(x, x.name) for x in self.db.Artist)
82 |
83 | @raises_exception(TypeError, 'In `getattr(x, 1)` second argument should be a string. Got: 1')
84 | @db_session
85 | def test_not_string(self):
86 | select(getattr(x, 1) for x in self.db.Artist)
87 |
88 | @raises_exception(TypeError, 'In `getattr(x, name)` second argument should be a string. Got: 1')
89 | @db_session
90 | def test_not_string(self):
91 | name = 1
92 | select(getattr(x, name) for x in self.db.Artist)
93 |
94 | @db_session
95 | def test_lambda_1(self):
96 | for name, value in [('name', 'Sia'), ('age', 40), ('name', 'Sia')]:
97 | result = self.db.Artist.select(lambda a: getattr(a, name) == value)
98 | self.assertEqual(set(obj.name for obj in result), {'Sia'})
99 |
100 | @db_session
101 | def test_lambda_2(self):
102 | for entity, name, value in [
103 | (self.db.Genre, 'name', 'Pop'),
104 | (self.db.Artist, 'age', 40),
105 | (self.db.Hobby, 'name', 'Swimming'),
106 | ]:
107 | result = entity.select(lambda a: getattr(a, name) == value)
108 | self.assertEqual(set(result[:]), {entity.select().first()})
109 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_hooks.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests import setup_database, teardown_database, db_params
7 |
8 | logged_events = []
9 |
10 | db = Database()
11 |
12 |
13 | class Person(db.Entity):
14 | id = PrimaryKey(int)
15 | name = Required(str)
16 | age = Required(int)
17 |
18 | def before_insert(self):
19 | logged_events.append('BI_' + self.name)
20 | do_before_insert(self)
21 |
22 | def before_update(self):
23 | logged_events.append('BU_' + self.name)
24 | do_before_update(self)
25 |
26 | def before_delete(self):
27 | logged_events.append('BD_' + self.name)
28 | do_before_delete(self)
29 |
30 | def after_insert(self):
31 | logged_events.append('AI_' + self.name)
32 | do_after_insert(self)
33 |
34 | def after_update(self):
35 | logged_events.append('AU_' + self.name)
36 | do_after_update(self)
37 |
38 | def after_delete(self):
39 | logged_events.append('AD_' + self.name)
40 | do_after_delete(self)
41 |
42 |
43 | def do_nothing(person):
44 | pass
45 |
46 |
47 | def set_hooks_to_do_nothing():
48 | global do_before_insert, do_before_update, do_before_delete
49 | global do_after_insert, do_after_update, do_after_delete
50 | do_before_insert = do_before_update = do_before_delete = do_nothing
51 | do_after_insert = do_after_update = do_after_delete = do_nothing
52 |
53 |
54 | db.bind(**db_params)
55 | db.generate_mapping(check_tables=False)
56 |
57 | set_hooks_to_do_nothing()
58 |
59 |
60 | def flush_for(*objects):
61 | for obj in objects:
62 | obj.flush()
63 |
64 |
65 | class TestHooks(unittest.TestCase):
66 | @classmethod
67 | def setUpClass(cls):
68 | setup_database(db)
69 |
70 | @classmethod
71 | def tearDownClass(cls):
72 | teardown_database(db)
73 |
74 | def setUp(self):
75 | set_hooks_to_do_nothing()
76 | with db_session:
77 | db.execute('delete from Person')
78 | p1 = Person(id=1, name='John', age=22)
79 | p2 = Person(id=2, name='Mary', age=18)
80 | p3 = Person(id=3, name='Mike', age=25)
81 | logged_events[:] = []
82 |
83 | def tearDown(self):
84 | pass
85 |
86 | @db_session
87 | def test_1a(self):
88 | p4 = Person(id=4, name='Bob', age=16)
89 | p5 = Person(id=5, name='Lucy', age=23)
90 | self.assertEqual(logged_events, [])
91 | db.flush()
92 | self.assertEqual(logged_events, ['BI_Bob', 'BI_Lucy', 'AI_Bob', 'AI_Lucy'])
93 |
94 | @db_session
95 | def test_1b(self):
96 | p4 = Person(id=4, name='Bob', age=16)
97 | p5 = Person(id=5, name='Lucy', age=23)
98 | self.assertEqual(logged_events, [])
99 | flush_for(p4, p5)
100 | self.assertEqual(logged_events, ['BI_Bob', 'AI_Bob', 'BI_Lucy', 'AI_Lucy'])
101 |
102 | @db_session
103 | def test_2a(self):
104 | p4 = Person(id=4, name='Bob', age=16)
105 | p1 = Person[1] # auto-flush here
106 | p2 = Person[2]
107 | self.assertEqual(logged_events, ['BI_Bob', 'AI_Bob'])
108 | p2.age += 1
109 | p5 = Person(id=5, name='Lucy', age=23)
110 | db.flush()
111 | self.assertEqual(logged_events, ['BI_Bob', 'AI_Bob', 'BU_Mary', 'BI_Lucy', 'AU_Mary', 'AI_Lucy'])
112 |
113 | @db_session
114 | def test_2b(self):
115 | p4 = Person(id=4, name='Bob', age=16)
116 | p1 = Person[1] # auto-flush here
117 | p2 = Person[2]
118 | self.assertEqual(logged_events, ['BI_Bob', 'AI_Bob'])
119 | p2.age += 1
120 | p5 = Person(id=5, name='Lucy', age=23)
121 | flush_for(p4, p2, p5)
122 | self.assertEqual(logged_events, ['BI_Bob', 'AI_Bob', 'BU_Mary', 'AU_Mary', 'BI_Lucy', 'AI_Lucy'])
123 |
124 | @db_session
125 | def test_3(self):
126 | global do_before_insert
127 | def do_before_insert(person):
128 | some_person = Person.select().first() # should not cause infinite recursion
129 | p4 = Person(id=4, name='Bob', age=16)
130 | db.flush()
131 |
132 | @db_session
133 | def test_4(self):
134 | global do_before_insert
135 | def do_before_insert(person):
136 | some_person = Person.select().first() # creates nested prefetch_context
137 | p4 = Person(id=4, name='Bob', age=16)
138 | Person.select().first()
139 |
140 |
141 | if __name__ == '__main__':
142 | unittest.main()
143 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_indexes.py:
--------------------------------------------------------------------------------
1 | import sys, unittest
2 | from decimal import Decimal
3 | from datetime import date
4 |
5 | from pony.orm import *
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import db_params, teardown_database
8 |
9 | class TestIndexes(unittest.TestCase):
10 | def setUp(self):
11 | self.db = Database(**db_params)
12 |
13 | def tearDown(self):
14 | teardown_database(self.db)
15 |
16 | def test_1(self):
17 | db = self.db
18 | class Person(db.Entity):
19 | name = Required(str)
20 | age = Required(int)
21 | composite_key(name, 'age')
22 | db.generate_mapping(create_tables=True)
23 |
24 | i1, i2 = Person._indexes_
25 | self.assertEqual(i1.attrs, (Person.id,))
26 | self.assertEqual(i1.is_pk, True)
27 | self.assertEqual(i1.is_unique, True)
28 | self.assertEqual(i2.attrs, (Person.name, Person.age))
29 | self.assertEqual(i2.is_pk, False)
30 | self.assertEqual(i2.is_unique, True)
31 |
32 | table_name = 'Person' if db.provider.dialect == 'SQLite' and pony.__version__ < '0.9' else 'person'
33 | table = db.schema.tables[table_name]
34 | name_column = table.column_dict['name']
35 | age_column = table.column_dict['age']
36 | self.assertEqual(len(table.indexes), 2)
37 | db_index = table.indexes[name_column, age_column]
38 | self.assertEqual(db_index.is_pk, False)
39 | self.assertEqual(db_index.is_unique, True)
40 |
41 | def test_2(self):
42 | db = self.db
43 | class Person(db.Entity):
44 | name = Required(str)
45 | age = Required(int)
46 | composite_index(name, 'age')
47 | db.generate_mapping(create_tables=True)
48 |
49 | i1, i2 = Person._indexes_
50 | self.assertEqual(i1.attrs, (Person.id,))
51 | self.assertEqual(i1.is_pk, True)
52 | self.assertEqual(i1.is_unique, True)
53 | self.assertEqual(i2.attrs, (Person.name, Person.age))
54 | self.assertEqual(i2.is_pk, False)
55 | self.assertEqual(i2.is_unique, False)
56 |
57 | table_name = 'Person' if db.provider.dialect == 'SQLite' and pony.__version__ < '0.9' else 'person'
58 | table = db.schema.tables[table_name]
59 | name_column = table.column_dict['name']
60 | age_column = table.column_dict['age']
61 | self.assertEqual(len(table.indexes), 2)
62 | db_index = table.indexes[name_column, age_column]
63 | self.assertEqual(db_index.is_pk, False)
64 | self.assertEqual(db_index.is_unique, False)
65 |
66 | create_script = db.schema.generate_create_script()
67 |
68 |
69 | dialect = self.db.provider.dialect
70 | if pony.__version__ < '0.9':
71 | if dialect == 'SQLite':
72 | index_sql = 'CREATE INDEX "idx_person__name_age" ON "Person" ("name", "age")'
73 | else:
74 | index_sql = 'CREATE INDEX "idx_person__name_age" ON "person" ("name", "age")'
75 | elif dialect == 'MySQL' or dialect == 'SQLite':
76 | index_sql = 'CREATE INDEX `idx_person__name__age` ON `person` (`name`, `age`)'
77 | elif dialect == 'PostgreSQL':
78 | index_sql = 'CREATE INDEX "idx_person__name__age" ON "person" ("name", "age")'
79 | elif dialect == 'Oracle':
80 | index_sql = 'CREATE INDEX "IDX_PERSON__NAME__AGE" ON "PERSON" ("NAME", "AGE")'
81 | else:
82 | raise NotImplementedError
83 | self.assertIn(index_sql, create_script)
84 |
85 | def test_3(self):
86 | db = self.db
87 | class User(db.Entity):
88 | name = Required(str, unique=True)
89 |
90 | db.generate_mapping(create_tables=True)
91 |
92 | with db_session:
93 | u = User(id=1, name='A')
94 |
95 | with db_session:
96 | u = User[1]
97 | u.name = 'B'
98 |
99 | with db_session:
100 | u = User[1]
101 | self.assertEqual(u.name, 'B')
102 |
103 | def test_4(self): # issue 321
104 | db = self.db
105 | class Person(db.Entity):
106 | name = Required(str)
107 | age = Required(int)
108 | composite_key(name, age)
109 |
110 | db.generate_mapping(create_tables=True)
111 | with db_session:
112 | p1 = Person(id=1, name='John', age=19)
113 |
114 | with db_session:
115 | p1 = Person[1]
116 | p1.set(name='John', age=19)
117 | p1.delete()
118 |
119 | def test_5(self):
120 | db = self.db
121 |
122 | class Table1(db.Entity):
123 | name = Required(str)
124 | table2s = Set('Table2')
125 |
126 | class Table2(db.Entity):
127 | height = Required(int)
128 | length = Required(int)
129 | table1 = Optional('Table1')
130 | composite_key(height, length, table1)
131 |
132 | db.generate_mapping(create_tables=True)
133 |
134 | with db_session:
135 | Table2(height=2, length=1)
136 | Table2.exists(height=2, length=1)
137 |
138 | if __name__ == '__main__':
139 | unittest.main()
140 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_inner_join_syntax.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony import orm
5 | from pony.orm.tests import setup_database, teardown_database, only_for
6 |
7 | db = Database()
8 |
9 |
10 | class Genre(db.Entity):
11 | name = orm.Optional(str) # TODO primary key
12 | artists = orm.Set('Artist')
13 | favorite = orm.Optional(bool)
14 | index = orm.Optional(int)
15 |
16 |
17 | class Hobby(db.Entity):
18 | name = orm.Required(str)
19 | artists = orm.Set('Artist')
20 |
21 |
22 | class Artist(db.Entity):
23 | name = orm.Required(str)
24 | age = orm.Optional(int)
25 | hobbies = orm.Set(Hobby)
26 | genres = orm.Set(Genre)
27 |
28 | pony.options.INNER_JOIN_SYNTAX = True
29 |
30 |
31 | @only_for('sqlite')
32 | class TestJoin(unittest.TestCase):
33 | exclude_fixtures = {'test': ['clear_tables']}
34 | @classmethod
35 | def setUpClass(cls):
36 | setup_database(db)
37 |
38 | with orm.db_session:
39 | pop = Genre(name='pop')
40 | rock = Genre(name='rock')
41 | Artist(name='Sia', age=40, genres=[pop, rock])
42 | Artist(name='Lady GaGa', age=30, genres=[pop])
43 |
44 | @classmethod
45 | def tearDownClass(cls):
46 | teardown_database(db)
47 |
48 | @db_session
49 | def test_join_1(self):
50 | result = select(g.id for g in db.Genre for a in g.artists if a.name.startswith('S'))[:]
51 | self.assertEqual(db.last_sql, """SELECT DISTINCT "g"."id"
52 | FROM "Genre" "g"
53 | INNER JOIN "Artist_Genre" "t-1"
54 | ON "g"."id" = "t-1"."genre"
55 | INNER JOIN "Artist" "a"
56 | ON "t-1"."artist" = "a"."id"
57 | WHERE "a"."name" LIKE 'S%'""")
58 |
59 | @db_session
60 | def test_join_2(self):
61 | result = select(g.id for g in db.Genre for a in db.Artist
62 | if JOIN(a in g.artists) and a.name.startswith('S'))[:]
63 | self.assertEqual(db.last_sql, """SELECT DISTINCT "g"."id"
64 | FROM "Genre" "g"
65 | INNER JOIN "Artist_Genre" "t-1"
66 | ON "g"."id" = "t-1"."genre", "Artist" "a"
67 | WHERE "t-1"."artist" = "a"."id"
68 | AND "a"."name" LIKE 'S%'""")
69 |
70 |
71 | @db_session
72 | def test_join_3(self):
73 | result = select(g.id for g in db.Genre for x in db.Artist for a in db.Artist
74 | if JOIN(a in g.artists) and a.name.startswith('S') and g.id == x.id)[:]
75 | self.assertEqual(db.last_sql, '''SELECT DISTINCT "g"."id"
76 | FROM "Genre" "g"
77 | INNER JOIN "Artist_Genre" "t-1"
78 | ON "g"."id" = "t-1"."genre", "Artist" "x", "Artist" "a"
79 | WHERE "t-1"."artist" = "a"."id"
80 | AND "a"."name" LIKE 'S%'
81 | AND "g"."id" = "x"."id"''')
82 |
83 | @db_session
84 | def test_join_4(self):
85 | result = select(g.id for g in db.Genre for a in db.Artist for x in db.Artist
86 | if JOIN(a in g.artists) and a.name.startswith('S') and g.id == x.id)[:]
87 | self.assertEqual(db.last_sql, '''SELECT DISTINCT "g"."id"
88 | FROM "Genre" "g"
89 | INNER JOIN "Artist_Genre" "t-1"
90 | ON "g"."id" = "t-1"."genre", "Artist" "a", "Artist" "x"
91 | WHERE "t-1"."artist" = "a"."id"
92 | AND "a"."name" LIKE 'S%'
93 | AND "g"."id" = "x"."id"''')
94 |
95 | if __name__ == '__main__':
96 | unittest.main()
97 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_int_converter.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony import orm
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 | class TestIntConverter1(unittest.TestCase):
10 | def setUp(self):
11 | self.db = db = orm.Database()
12 |
13 | class Foo(db.Entity):
14 | id = orm.PrimaryKey(int)
15 | x = orm.Required(int, size=8, unsigned=True)
16 |
17 | setup_database(db)
18 |
19 | with orm.db_session:
20 | foo = Foo(id=123, x=1)
21 |
22 | def tearDown(self):
23 | teardown_database(self.db)
24 |
25 | def test_1(self):
26 | with orm.db_session:
27 | foo = self.db.Foo[123]
28 | foo.x -= 1
29 | with orm.db_session:
30 | foo = self.db.Foo[123]
31 | self.assertEqual(foo.x, 0)
32 |
33 | @raises_exception(ValueError, "Value -1 of attr Foo.x is less than the minimum allowed value 0")
34 | @orm.db_session
35 | def test_2(self):
36 | foo = self.db.Foo[123]
37 | foo.x -= 2
38 |
39 | @orm.db_session
40 | def test_3(self):
41 | with orm.db_session:
42 | foo = self.db.Foo[123]
43 | foo.x += 254
44 | with orm.db_session:
45 | foo = self.db.Foo[123]
46 | self.assertEqual(foo.x, 255)
47 |
48 | @raises_exception(ValueError, "Value 256 of attr Foo.x is greater than the maximum allowed value 255")
49 | @orm.db_session
50 | def test_4(self):
51 | foo = self.db.Foo[123]
52 | foo.x += 255
53 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_interleave.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import raises_exception
7 | from pony.orm.tests import db_params, only_for
8 |
9 | @only_for(providers=['cockroach'])
10 | class TestDiag(unittest.TestCase):
11 | @raises_exception(TypeError, '`interleave` option cannot be specified for Set attribute Foo.x')
12 | def test_1(self):
13 | db = Database()
14 | class Foo(db.Entity):
15 | x = Set('Bar', interleave=True)
16 | class Bar(db.Entity):
17 | y = Required('Foo')
18 |
19 | @raises_exception(TypeError, "`interleave` option value should be True, False or None. Got: 'yes'")
20 | def test_2(self):
21 | db = Database()
22 | class Foo(db.Entity):
23 | x = Required('Bar', interleave='yes')
24 | class Bar(db.Entity):
25 | y = Set('Foo')
26 |
27 | @raises_exception(TypeError, 'only one attribute may be marked as interleave. Got: Foo.x, Foo.y')
28 | def test_3(self):
29 | db = Database()
30 | class Foo(db.Entity):
31 | x = Required(int, interleave=True)
32 | y = Required(int, interleave=True)
33 |
34 | @raises_exception(TypeError, 'Interleave attribute should be part of relationship. Got: Foo.x')
35 | def test_4(self):
36 | db = Database()
37 | class Foo(db.Entity):
38 | x = Required(int, interleave=True)
39 |
40 | def test_5(self):
41 | db = Database(**db_params)
42 | class Bar(db.Entity):
43 | y = Set('Foo')
44 |
45 | class Foo(db.Entity):
46 | x = Required('Bar', interleave=True)
47 | id = Required(int)
48 | PrimaryKey(x, id)
49 |
50 | db.generate_mapping(create_tables=True)
51 | s = ') INTERLEAVE IN PARENT "bar" ("x")'
52 | self.assertIn(s, db.schema.tables['foo'].get_create_command())
53 | db.drop_all_tables()
54 |
55 |
56 | if __name__ == '__main__':
57 | unittest.main()
--------------------------------------------------------------------------------
/pony/orm/tests/test_isinstance.py:
--------------------------------------------------------------------------------
1 | from datetime import date
2 | from decimal import Decimal
3 |
4 | import unittest
5 |
6 | from pony.orm import *
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import setup_database, teardown_database, only_for
9 |
10 | db = Database()
11 |
12 |
13 | class Person(db.Entity):
14 | id = PrimaryKey(int, auto=True)
15 | name = Required(str)
16 | dob = Optional(date)
17 | ssn = Required(str, unique=True)
18 |
19 |
20 | class Student(Person):
21 | group = Required("Group")
22 | mentor = Optional("Teacher")
23 | attend_courses = Set("Course")
24 |
25 |
26 | class Teacher(Person):
27 | teach_courses = Set("Course")
28 | apprentices = Set("Student")
29 | salary = Required(Decimal)
30 |
31 |
32 | class Assistant(Student, Teacher):
33 | pass
34 |
35 |
36 | class Professor(Teacher):
37 | position = Required(str)
38 |
39 |
40 | class Group(db.Entity):
41 | number = PrimaryKey(int)
42 | students = Set("Student")
43 |
44 |
45 | class Course(db.Entity):
46 | name = Required(str)
47 | semester = Required(int)
48 | students = Set(Student)
49 | teachers = Set(Teacher)
50 | PrimaryKey(name, semester)
51 |
52 |
53 | class TestVolatile(unittest.TestCase):
54 | @classmethod
55 | def setUpClass(cls):
56 | setup_database(db)
57 | with db_session:
58 | p = Person(name='Person1', ssn='SSN1')
59 | g = Group(number=123)
60 | prof = Professor(name='Professor1', salary=1000, position='position1', ssn='SSN5')
61 | a1 = Assistant(name='Assistant1', group=g, salary=100, ssn='SSN4', mentor=prof)
62 | a2 = Assistant(name='Assistant2', group=g, salary=200, ssn='SSN6', mentor=prof)
63 | s1 = Student(name='Student1', group=g, ssn='SSN2', mentor=a1)
64 | s2 = Student(name='Student2', group=g, ssn='SSN3')
65 |
66 | @classmethod
67 | def tearDownClass(cls):
68 | teardown_database(db)
69 |
70 | @db_session
71 | def test_1(self):
72 | q = select(p.name for p in Person if isinstance(p, Student))
73 | self.assertEqual(set(q), {'Student1', 'Student2', 'Assistant1', 'Assistant2'})
74 |
75 | @db_session
76 | def test_2(self):
77 | q = select(p.name for p in Person if not isinstance(p, Student))
78 | self.assertEqual(set(q), {'Person1', 'Professor1'})
79 |
80 | @db_session
81 | def test_3(self):
82 | q = select(p.name for p in Student if isinstance(p, Professor))
83 | self.assertEqual(set(q), set())
84 |
85 | @db_session
86 | def test_4(self):
87 | q = select(p.name for p in Person if not isinstance(p, Person))
88 | self.assertEqual(set(q), set())
89 |
90 | @db_session
91 | def test_5(self):
92 | q = select(p.name for p in Person if isinstance(p, (Student, Teacher)))
93 | self.assertEqual(set(q), {'Student1', 'Student2', 'Assistant1', 'Assistant2', 'Professor1'})
94 |
95 | @db_session
96 | def test_6(self):
97 | q = select(p.name for p in Person if isinstance(p, Student) and isinstance(p, Teacher))
98 | self.assertEqual(set(q), {'Assistant1', 'Assistant2'})
99 |
100 | @db_session
101 | def test_7(self):
102 | q = select(p.name for p in Person
103 | if (isinstance(p, Student) and p.ssn == 'SSN2')
104 | or (isinstance(p, Professor) and p.salary > 500))
105 | self.assertEqual(set(q), {'Student1', 'Professor1'})
106 |
107 | @db_session
108 | def test_8(self):
109 | q = select(p.name for p in Person if isinstance(p, Person))
110 | self.assertEqual(set(q), {'Person1', 'Student1', 'Student2', 'Assistant1', 'Assistant2', 'Professor1'})
111 |
112 | @db_session
113 | def test_9(self):
114 | q = select(g.number for g in Group if isinstance(g, Group))
115 | self.assertEqual(set(q), {123})
116 |
117 |
118 | if __name__ == '__main__':
119 | unittest.main()
120 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_lambda.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from datetime import datetime, timedelta
3 |
4 | from pony.orm import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 |
10 | class User(db.Entity):
11 | id = PrimaryKey(int)
12 | login = Required(str)
13 | password = Required(str)
14 | created_at = Required(datetime, default=datetime.now())
15 |
16 |
17 | class TestLambda(unittest.TestCase):
18 | @classmethod
19 | def setUpClass(cls) -> None:
20 | setup_database(db)
21 |
22 | @classmethod
23 | def setUp(self) -> None:
24 | with db_session:
25 | User(id=1, login='test', password='123456', created_at=datetime(2012, 12, 13, 5, 25, 30))
26 | User(id=2, login='test2', password='123456', created_at=datetime(2015, 12, 13, 5, 25, 30))
27 | User(id=3, login='test3', password='123456')
28 |
29 | @classmethod
30 | def tearDownClass(cls) -> None:
31 | teardown_database(db)
32 |
33 | @classmethod
34 | def tearDown(self) -> None:
35 | with db_session:
36 | User.select().delete()
37 |
38 | @db_session
39 | def test_select(self):
40 | result = User.select(lambda u: u.created_at < datetime.now() - timedelta(days=365))[:]
41 | self.assertEqual([u.id for u in result], [1, 2])
42 |
43 | @db_session
44 | def test_order_by_1(self):
45 | result = User.select().order_by(lambda u: u.id)
46 | self.assertEqual([u.id for u in result], [1, 2, 3])
47 |
48 | @db_session
49 | def test_order_by_2(self):
50 | result = User.select().order_by(lambda u: desc(u.id))
51 | self.assertEqual([u.id for u in result], [3, 2, 1])
52 |
53 | @db_session
54 | def test_order_by_3(self):
55 | result = User.select().order_by(lambda u: (u.login, u.id))
56 | self.assertEqual([u.id for u in result], [1, 2, 3])
57 |
58 | @db_session
59 | def test_order_by_4(self):
60 | result = User.select().order_by(lambda u: (desc(u.login), desc(u.id)))
61 | self.assertEqual([u.id for u in result], [3, 2, 1])
62 |
63 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_lazy.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests import setup_database, teardown_database
7 |
8 |
9 | class TestLazy(unittest.TestCase):
10 | def setUp(self):
11 | db = self.db = Database()
12 | class X(self.db.Entity):
13 | a = Required(int)
14 | b = Required(str, lazy=True)
15 | self.X = X
16 | setup_database(db)
17 | with db_session:
18 | x1 = X(id=1, a=1, b='first')
19 | x2 = X(id=2, a=2, b='second')
20 | x3 = X(id=3, a=3, b='third')
21 |
22 | def tearDown(self):
23 | teardown_database(self.db)
24 |
25 | @db_session
26 | def test_lazy_1(self):
27 | X = self.X
28 | x1 = X[1]
29 | self.assertTrue(X.a in x1._vals_)
30 | self.assertTrue(X.b not in x1._vals_)
31 | b = x1.b
32 | self.assertEqual(b, 'first')
33 |
34 | @db_session
35 | def test_lazy_2(self):
36 | X = self.X
37 | x1 = X[1]
38 | x2 = X[2]
39 | x3 = X[3]
40 | self.assertTrue(X.b not in x1._vals_)
41 | self.assertTrue(X.b not in x2._vals_)
42 | self.assertTrue(X.b not in x3._vals_)
43 | b = x1.b
44 | self.assertTrue(X.b in x1._vals_)
45 | self.assertTrue(X.b not in x2._vals_)
46 | self.assertTrue(X.b not in x3._vals_)
47 |
48 | @db_session
49 | def test_lazy_3(self): # coverage of https://github.com/ponyorm/pony/issues/49
50 | X = self.X
51 | x1 = X.get(b='first')
52 | self.assertTrue(X._bits_[X.b] & x1._rbits_)
53 | self.assertTrue(X.b, x1._vals_)
54 |
55 | @db_session
56 | def test_lazy_4(self): # coverage of https://github.com/ponyorm/pony/issues/49
57 | X = self.X
58 | result = select(x for x in X if x.b == 'first')[:]
59 | for x in result:
60 | self.assertTrue(X._bits_[X.b] & x._rbits_)
61 | self.assertTrue(X.b in x._vals_)
62 |
63 | @db_session
64 | def test_lazy_5(self): # coverage of https://github.com/ponyorm/pony/issues/49
65 | X = self.X
66 | result = select(x for x in X if x.b == 'first' if count() > 0)[:]
67 | for x in result:
68 | self.assertFalse(X._bits_[X.b] & x._rbits_)
69 | self.assertTrue(X.b not in x._vals_)
70 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_objects_to_save_cleanup.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests import setup_database, teardown_database
5 |
6 | class EntityStatusTestCase(object):
7 | @classmethod
8 | def setUpClass(cls):
9 | db = cls.db = Database()
10 |
11 | class TestPost(db.Entity):
12 | category = Optional('TestCategory')
13 | name = Optional(str, default='Noname')
14 |
15 | class TestCategory(db.Entity):
16 | posts = Set(TestPost)
17 |
18 | setup_database(db)
19 |
20 | @classmethod
21 | def tearDownClass(cls):
22 | teardown_database(cls.db)
23 |
24 | def make_flush(self, obj=None):
25 | raise NotImplementedError
26 |
27 | @db_session
28 | def test_delete_updated(self):
29 | p = self.db.TestPost()
30 | self.make_flush(p)
31 | p.name = 'Pony'
32 | self.assertEqual(p._status_, 'modified')
33 | self.make_flush(p)
34 | self.assertEqual(p._status_, 'updated')
35 | p.delete()
36 | self.assertEqual(p._status_, 'marked_to_delete')
37 | self.make_flush(p)
38 | self.assertEqual(p._status_, 'deleted')
39 |
40 | @db_session
41 | def test_delete_inserted(self):
42 | p = self.db.TestPost()
43 | self.assertEqual(p._status_, 'created')
44 | self.make_flush(p)
45 | self.assertEqual(p._status_, 'inserted')
46 | p.delete()
47 |
48 | @db_session
49 | def test_cancelled(self):
50 | p = self.db.TestPost()
51 | self.assertEqual(p._status_, 'created')
52 | p.delete()
53 | self.assertEqual(p._status_, 'cancelled')
54 | self.make_flush(p)
55 | self.assertEqual(p._status_, 'cancelled')
56 |
57 |
58 | class EntityStatusTestCase_ObjectFlush(EntityStatusTestCase,
59 | unittest.TestCase):
60 |
61 | def make_flush(self, obj=None):
62 | obj.flush()
63 |
64 |
65 | class EntityStatusTestCase_FullFlush(EntityStatusTestCase,
66 | unittest.TestCase):
67 |
68 | def make_flush(self, obj=None):
69 | flush() # full flush
70 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_random.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests.testutils import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 |
10 | class Person(db.Entity):
11 | id = PrimaryKey(int)
12 | name = Required(str)
13 |
14 |
15 | class TestRandom(unittest.TestCase):
16 | @classmethod
17 | def setUpClass(cls):
18 | setup_database(db)
19 | with db_session:
20 | Person(id=1, name='John')
21 | Person(id=2, name='Mary')
22 | Person(id=3, name='Bob')
23 | Person(id=4, name='Mike')
24 | Person(id=5, name='Ann')
25 |
26 | @classmethod
27 | def tearDownClass(cls):
28 | teardown_database(db)
29 |
30 | @db_session
31 | def test_1(self):
32 | persons = Person.select().random(2)
33 | self.assertEqual(len(persons), 2)
34 | p1, p2 = persons
35 | self.assertNotEqual(p1.id, p2.id)
36 | self.assertTrue(p1.id in range(1, 6))
37 | self.assertTrue(p2.id in range(1, 6))
38 |
39 | @db_session
40 | def test_2(self):
41 | persons = Person.select_random(2)
42 | self.assertEqual(len(persons), 2)
43 | p1, p2 = persons
44 | self.assertNotEqual(p1.id, p2.id)
45 | self.assertTrue(p1.id in range(1, 6))
46 | self.assertTrue(p2.id in range(1, 6))
47 |
48 | if __name__ == '__main__':
49 | unittest.main()
50 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_relations_one2one3.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import setup_database, teardown_database, only_for
8 |
9 |
10 | @only_for('sqlite')
11 | class TestOneToOne3(unittest.TestCase):
12 | def setUp(self):
13 | self.db = Database()
14 |
15 | class Person(self.db.Entity):
16 | name = Required(str)
17 | passport = Optional("Passport", cascade_delete=True)
18 |
19 | class Passport(self.db.Entity):
20 | code = Required(str)
21 | person = Required("Person")
22 |
23 | setup_database(self.db)
24 |
25 | with db_session:
26 | p1 = Person(name='John')
27 | Passport(code='123', person=p1)
28 |
29 | def tearDown(self):
30 | teardown_database(self.db)
31 |
32 | @db_session
33 | def test_1(self):
34 | obj = select(p for p in self.db.Person if p.passport.id).first()
35 | self.assertEqual(obj.name, 'John')
36 | self.assertEqual(obj.passport.code, '123')
37 |
38 | @db_session
39 | def test_2(self):
40 | select(p for p in self.db.Person if p.passport is None)[:]
41 | sql = self.db.last_sql
42 | self.assertEqual(sql, '''SELECT "p"."id", "p"."name"
43 | FROM "Person" "p"
44 | LEFT JOIN "Passport" "passport"
45 | ON "p"."id" = "passport"."person"
46 | WHERE "passport"."id" IS NULL''')
47 |
48 | @db_session
49 | def test_3(self):
50 | select(p for p in self.db.Person if not p.passport)[:]
51 | sql = self.db.last_sql
52 | self.assertEqual(sql, '''SELECT "p"."id", "p"."name"
53 | FROM "Person" "p"
54 | LEFT JOIN "Passport" "passport"
55 | ON "p"."id" = "passport"."person"
56 | WHERE "passport"."id" IS NULL''')
57 |
58 | @db_session
59 | def test_4(self):
60 | select(p for p in self.db.Person if p.passport)[:]
61 | sql = self.db.last_sql
62 | self.assertEqual(sql, '''SELECT "p"."id", "p"."name"
63 | FROM "Person" "p"
64 | LEFT JOIN "Passport" "passport"
65 | ON "p"."id" = "passport"."person"
66 | WHERE "passport"."id" IS NOT NULL''')
67 |
68 | @db_session
69 | def test_5(self):
70 | p = self.db.Person.get(name='John')
71 | p.delete()
72 | flush()
73 | sql = self.db.last_sql
74 | self.assertEqual(sql, '''DELETE FROM "Person"
75 | WHERE "id" = ?''')
76 |
77 | @raises_exception(ConstraintError, 'Cannot unlink Passport[1] from previous Person[1] object, because Passport.person attribute is required')
78 | @db_session
79 | def test_6(self):
80 | p = self.db.Person.get(name='John')
81 | self.db.Passport(code='456', person=p)
82 |
83 | @raises_exception(ConstraintError, 'Cannot unlink Passport[1] from previous Person[1] object, because Passport.person attribute is required')
84 | @db_session
85 | def test7(self):
86 | p2 = self.db.Person(name='Mike')
87 | pas2 = self.db.Passport(code='456', person=p2)
88 | commit()
89 | p1 = self.db.Person.get(name='John')
90 | pas2.person = p1
91 |
92 | if __name__ == '__main__':
93 | unittest.main()
94 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_relations_one2one4.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import *
7 | from pony.orm.tests import setup_database, teardown_database
8 |
9 | db = Database()
10 |
11 | class Person(db.Entity):
12 | name = Required(str)
13 | passport = Optional("Passport")
14 |
15 | class Passport(db.Entity):
16 | code = Required(str)
17 | person = Required("Person")
18 |
19 | class TestOneToOne4(unittest.TestCase):
20 | def setUp(self):
21 | setup_database(db)
22 | with db_session:
23 | p1 = Person(id=1, name='John')
24 | Passport(id=1, code='123', person=p1)
25 |
26 | def tearDown(self):
27 | teardown_database(db)
28 |
29 | @raises_exception(ConstraintError, 'Cannot unlink Passport[1] from previous Person[1] object, because Passport.person attribute is required')
30 | @db_session
31 | def test1(self):
32 | p2 = Person(id=2, name='Mike')
33 | pas2 = Passport(id=2, code='456', person=p2)
34 | commit()
35 | p1 = Person.get(name='John')
36 | pas2.person = p1
37 |
38 | if __name__ == '__main__':
39 | unittest.main()
40 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_relations_symmetric_m2m.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from pony.orm.core import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 |
10 | class Person(db.Entity):
11 | name = Required(str)
12 | friends = Set('Person', reverse='friends')
13 |
14 |
15 | class TestSymmetricM2M(unittest.TestCase):
16 | @classmethod
17 | def setUpClass(cls):
18 | setup_database(db)
19 |
20 | @classmethod
21 | def tearDownClass(cls):
22 | teardown_database(db)
23 |
24 | def setUp(self):
25 | with db_session:
26 | for p in Person.select(): p.delete()
27 | with db_session:
28 | db.insert(Person, id=1, name='A')
29 | db.insert(Person, id=2, name='B')
30 | db.insert(Person, id=3, name='C')
31 | db.insert(Person, id=4, name='D')
32 | db.insert(Person, id=5, name='E')
33 | db.insert(Person.friends, person=1, person_2=2)
34 | db.insert(Person.friends, person=2, person_2=1)
35 | db.insert(Person.friends, person=1, person_2=3)
36 | db.insert(Person.friends, person=3, person_2=1)
37 | db_session.__enter__()
38 | def tearDown(self):
39 | rollback()
40 | db_session.__exit__()
41 | def test1a(self):
42 | p1 = Person[1]
43 | p4 = Person[4]
44 | p1.friends.add(p4)
45 | self.assertEqual(set(p4.friends), {p1})
46 | def test1b(self):
47 | p1 = Person[1]
48 | p4 = Person[4]
49 | p1.friends.add(p4)
50 | self.assertEqual(set(p1.friends), {Person[2], Person[3], p4})
51 | def test1c(self):
52 | p1 = Person[1]
53 | p4 = Person[4]
54 | p1.friends.add(p4)
55 | commit()
56 | rows = db.select("* from person_friends order by person, person_2")
57 | self.assertEqual(rows, [(1,2), (1,3), (1,4), (2,1), (3,1), (4,1)])
58 | def test2a(self):
59 | p1 = Person[1]
60 | p2 = Person[2]
61 | p1.friends.remove(p2)
62 | self.assertEqual(set(p1.friends), {Person[3]})
63 | def test2b(self):
64 | p1 = Person[1]
65 | p2 = Person[2]
66 | p1.friends.remove(p2)
67 | self.assertEqual(set(Person[3].friends), {p1})
68 | def test2c(self):
69 | p1 = Person[1]
70 | p2 = Person[2]
71 | p1.friends.remove(p2)
72 | self.assertEqual(set(p2.friends), set())
73 | def test2d(self):
74 | p1 = Person[1]
75 | p2 = Person[2]
76 | p1.friends.remove(p2)
77 | commit()
78 | rows = db.select("* from person_friends order by person, person_2")
79 | self.assertEqual(rows, [(1,3), (3,1)])
80 | def test3a(self):
81 | db.execute('delete from person_friends')
82 | db.insert(Person.friends, person=1, person_2=2)
83 | p1 = Person[1]
84 | p2 = Person[2]
85 | p2_friends = set(p2.friends)
86 | self.assertEqual(p2_friends, set())
87 | try: p1_friends = set(p1.friends)
88 | except UnrepeatableReadError as e: self.assertEqual(e.args[0],
89 | "Phantom object Person[1] appeared in collection Person[2].friends")
90 | else: self.fail()
91 | def test3b(self):
92 | db.execute('delete from person_friends')
93 | db.insert(Person.friends, person=1, person_2=2)
94 | p1 = Person[1]
95 | p2 = Person[2]
96 | p1_friends = set(p1.friends)
97 | self.assertEqual(p1_friends, {p2})
98 | try: p2_friends = set(p2.friends)
99 | except UnrepeatableReadError as e: self.assertEqual(e.args[0],
100 | "Phantom object Person[1] disappeared from collection Person[2].friends")
101 | else: self.fail()
102 |
103 | if __name__ == '__main__':
104 | unittest.main()
105 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_relations_symmetric_one2one.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 |
5 | from pony.orm.core import *
6 | from pony.orm.tests.testutils import raises_exception
7 | from pony.orm.tests import setup_database, teardown_database, only_for
8 |
9 | db = Database()
10 |
11 |
12 | class Person(db.Entity):
13 | name = Required(str)
14 | spouse = Optional('Person', reverse='spouse')
15 |
16 |
17 | class TestSymmetricOne2One(unittest.TestCase):
18 | @classmethod
19 | def setUpClass(cls):
20 | setup_database(db)
21 |
22 | @classmethod
23 | def tearDownClass(cls):
24 | teardown_database(db)
25 |
26 | def setUp(self):
27 | with db_session:
28 | db.execute('update person set spouse=null')
29 | db.execute('delete from person')
30 | db.insert(Person, id=1, name='A')
31 | db.insert(Person, id=2, name='B', spouse=1)
32 | db.execute('update person set spouse=2 where id=1')
33 | db.insert(Person, id=3, name='C')
34 | db.insert(Person, id=4, name='D', spouse=3)
35 | db.execute('update person set spouse=4 where id=3')
36 | db.insert(Person, id=5, name='E', spouse=None)
37 | db_session.__enter__()
38 | def tearDown(self):
39 | db_session.__exit__()
40 | def test1(self):
41 | p1 = Person[1]
42 | p2 = Person[2]
43 | p5 = Person[5]
44 | p1.spouse = p5
45 | commit()
46 | self.assertEqual(p1._vals_.get(Person.spouse), p5)
47 | self.assertEqual(p5._vals_.get(Person.spouse), p1)
48 | self.assertEqual(p2._vals_.get(Person.spouse), None)
49 | data = db.select('spouse from person order by id')
50 | self.assertEqual([5, None, 4, 3, 1], data)
51 | def test2(self):
52 | p1 = Person[1]
53 | p2 = Person[2]
54 | p1.spouse = None
55 | commit()
56 | self.assertEqual(p1._vals_.get(Person.spouse), None)
57 | self.assertEqual(p2._vals_.get(Person.spouse), None)
58 | data = db.select('spouse from person order by id')
59 | self.assertEqual([None, None, 4, 3, None], data)
60 | def test3(self):
61 | p1 = Person[1]
62 | p2 = Person[2]
63 | p3 = Person[3]
64 | p4 = Person[4]
65 | p1.spouse = p3
66 | commit()
67 | self.assertEqual(p1._vals_.get(Person.spouse), p3)
68 | self.assertEqual(p2._vals_.get(Person.spouse), None)
69 | self.assertEqual(p3._vals_.get(Person.spouse), p1)
70 | self.assertEqual(p4._vals_.get(Person.spouse), None)
71 | data = db.select('spouse from person order by id')
72 | self.assertEqual([3, None, 1, None, None], data)
73 | def test4(self):
74 | persons = set(select(p for p in Person if p.spouse.name in ('B', 'D')))
75 | self.assertEqual(persons, {Person[1], Person[3]})
76 | @raises_exception(UnrepeatableReadError, 'Multiple Person objects linked with the same Person[2] object. '
77 | 'Maybe Person.spouse attribute should be Set instead of Optional')
78 | def test5(self):
79 | db.execute('update person set spouse = 3 where id = 2')
80 | p1 = Person[1]
81 | p1.spouse
82 | p2 = Person[2]
83 | p2.name
84 | def test6(self):
85 | db.execute('update person set spouse = 3 where id = 2')
86 | p1 = Person[1]
87 | p2 = Person[2]
88 | p2.name
89 | p1.spouse
90 | self.assertEqual(p2._vals_.get(Person.spouse), p1)
91 |
92 | if __name__ == '__main__':
93 | unittest.main()
94 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_seeds.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import absolute_import, print_function, division
3 |
4 | import unittest
5 |
6 | from pony.orm.core import *
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import teardown_database, setup_database
9 |
10 | db = Database()
11 |
12 |
13 | class Group(db.Entity):
14 | id = PrimaryKey(int)
15 | number = Required(str, unique=True)
16 | students = Set("Student")
17 |
18 |
19 | class Student(db.Entity):
20 | id = PrimaryKey(int)
21 | name = Required(str)
22 | group = Required("Group")
23 |
24 |
25 | class TestCRUD(unittest.TestCase):
26 | @classmethod
27 | def setUpClass(cls):
28 | setup_database(db)
29 | with db_session:
30 | g1 = Group(id=1, number='g111')
31 | g2 = Group(id=2, number='g222')
32 | s1 = Student(id=1, name='S1', group=g1)
33 | s2 = Student(id=2, name='S2', group=g1)
34 | s3 = Student(id=3, name='S3', group=g2)
35 |
36 | @classmethod
37 | def tearDownClass(cls):
38 | teardown_database(db)
39 |
40 | def setUp(self):
41 | rollback()
42 | db_session.__enter__()
43 |
44 | def tearDown(self):
45 | rollback()
46 | db_session.__exit__()
47 |
48 | def test_unique_load(self):
49 | s1 = Student[1]
50 | g1 = s1.group
51 | g1.number = 'g123'
52 | self.assertEqual(g1.number, 'g123')
53 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_show.py:
--------------------------------------------------------------------------------
1 | import io, sys, unittest
2 | import contextlib
3 | from decimal import Decimal
4 | from datetime import date
5 |
6 | from pony.orm import *
7 | from pony.orm.tests.testutils import *
8 | from pony.orm.tests import setup_database, teardown_database
9 |
10 | db = Database()
11 |
12 |
13 | class Student(db.Entity):
14 | name = Required(str)
15 | scholarship = Optional(int)
16 | gpa = Optional(Decimal, 3, 1)
17 | dob = Optional(date)
18 | group = Required('Group')
19 | courses = Set('Course')
20 | biography = Optional(LongUnicode)
21 |
22 | class Group(db.Entity):
23 | number = PrimaryKey(int)
24 | students = Set(Student)
25 |
26 | class Course(db.Entity):
27 | name = Required(str, unique=True)
28 | students = Set(Student)
29 |
30 |
31 | normal_stdout = sys.stdout
32 |
33 |
34 | class TestShow(unittest.TestCase):
35 | @classmethod
36 | def setUpClass(cls):
37 | setup_database(db)
38 |
39 | with db_session:
40 | g1 = Group(number=1)
41 | g2 = Group(number=2)
42 | c1 = Course(name='Math')
43 | c2 = Course(name='Physics')
44 | c3 = Course(name='Computer Science')
45 | Student(id=1, name='S1', group=g1, gpa=3.1, courses=[c1, c2], biography='some text')
46 | Student(id=2, name='S2', group=g1, gpa=3.2, scholarship=100, dob=date(2000, 1, 1))
47 | Student(id=3, name='S3', group=g1, gpa=3.3, scholarship=200, dob=date(2001, 1, 2), courses=[c2, c3])
48 |
49 | @classmethod
50 | def tearDownClass(cls):
51 | teardown_database(db)
52 |
53 | def setUp(self):
54 | rollback()
55 | db_session.__enter__()
56 |
57 | def tearDown(self):
58 | rollback()
59 | db_session.__exit__()
60 |
61 | def test_1(self):
62 | f = io.StringIO()
63 | with contextlib.redirect_stdout(f):
64 | Student.select().show()
65 | self.assertEqual('\n' + f.getvalue().replace(' ', '~'), '''
66 | id|name|scholarship|gpa|dob~~~~~~~|group~~~
67 | --+----+-----------+---+----------+--------
68 | 1~|S1~~|None~~~~~~~|3.1|None~~~~~~|Group[1]
69 | 2~|S2~~|100~~~~~~~~|3.2|2000-01-01|Group[1]
70 | 3~|S3~~|200~~~~~~~~|3.3|2001-01-02|Group[1]
71 | ''')
72 |
73 | def test_2(self):
74 | f = io.StringIO()
75 | with contextlib.redirect_stdout(f):
76 | Group.select().show()
77 | self.assertEqual('\n' + f.getvalue().replace(' ', '~'), '''
78 | number
79 | ------
80 | 1~~~~~
81 | 2~~~~~
82 | ''')
83 |
84 |
85 | if __name__ == '__main__':
86 | unittest.main()
87 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_sqlbuilding_formatstyles.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from pony.orm.sqlbuilding import SQLBuilder
5 | from pony.orm.dbapiprovider import DBAPIProvider
6 | from pony.orm.tests.testutils import TestPool
7 |
8 |
9 | class TestFormatStyles(unittest.TestCase):
10 | def setUp(self):
11 | self.key1 = 'KEY1'
12 | self.key2 = 'KEY2'
13 | self.provider = DBAPIProvider(_database=None, pony_pool_mockup=TestPool(None))
14 | self.ast = [ 'SELECT', [ 'ALL', ['COLUMN', None, 'A']], [ 'FROM', [None, 'TABLE', 'T1']],
15 | [ 'WHERE', [ 'EQ', ['COLUMN', None, 'B'], [ 'PARAM', self.key1 ] ],
16 | [ 'EQ', ['COLUMN', None, 'C'], [ 'PARAM', self.key2 ] ],
17 | [ 'EQ', ['COLUMN', None, 'D'], [ 'PARAM', self.key2 ] ],
18 | [ 'EQ', ['COLUMN', None, 'E'], [ 'PARAM', self.key1 ] ]
19 | ]
20 | ]
21 | def test_qmark(self):
22 | self.provider.paramstyle = 'qmark'
23 | b = SQLBuilder(self.provider, self.ast)
24 | self.assertEqual(b.sql, 'SELECT "A"\n'
25 | 'FROM "T1"\n'
26 | 'WHERE "B" = ?\n AND "C" = ?\n AND "D" = ?\n AND "E" = ?')
27 | self.assertEqual(b.layout, [self.key1, self.key2, self.key2, self.key1])
28 | def test_numeric(self):
29 | self.provider.paramstyle = 'numeric'
30 | b = SQLBuilder(self.provider, self.ast)
31 | self.assertEqual(b.sql, 'SELECT "A"\n'
32 | 'FROM "T1"\n'
33 | 'WHERE "B" = :1\n AND "C" = :2\n AND "D" = :2\n AND "E" = :1')
34 | self.assertEqual(b.layout, [self.key1, self.key2, self.key2, self.key1])
35 | def test_named(self):
36 | self.provider.paramstyle = 'named'
37 | b = SQLBuilder(self.provider, self.ast)
38 | self.assertEqual(b.sql, 'SELECT "A"\n'
39 | 'FROM "T1"\n'
40 | 'WHERE "B" = :p1\n AND "C" = :p2\n AND "D" = :p2\n AND "E" = :p1')
41 | self.assertEqual(b.layout, [self.key1, self.key2, self.key2, self.key1])
42 | def test_format(self):
43 | self.provider.paramstyle = 'format'
44 | b = SQLBuilder(self.provider, self.ast)
45 | self.assertEqual(b.sql, 'SELECT "A"\n'
46 | 'FROM "T1"\n'
47 | 'WHERE "B" = %s\n AND "C" = %s\n AND "D" = %s\n AND "E" = %s')
48 | self.assertEqual(b.layout, [self.key1, self.key2, self.key2, self.key1])
49 | def test_pyformat(self):
50 | self.provider.paramstyle = 'pyformat'
51 | b = SQLBuilder(self.provider, self.ast)
52 | self.assertEqual(b.sql, 'SELECT "A"\n'
53 | 'FROM "T1"\n'
54 | 'WHERE "B" = %(p1)s\n AND "C" = %(p2)s\n AND "D" = %(p2)s\n AND "E" = %(p1)s')
55 | self.assertEqual(b.layout, [self.key1, self.key2, self.key2, self.key1])
56 |
57 |
58 | if __name__ == "__main__":
59 | unittest.main()
60 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_sqlbuilding_sqlast.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import unittest
4 | from pony.orm.core import Database, db_session
5 | from pony.orm.sqlsymbols import *
6 | from pony.orm.tests import setup_database, only_for
7 |
8 |
9 | @only_for('sqlite')
10 | class TestSQLAST(unittest.TestCase):
11 | def setUp(self):
12 | self.db = Database()
13 | setup_database(self.db)
14 | with db_session:
15 | conn = self.db.get_connection()
16 | conn.executescript("""
17 | create table if not exists T1(
18 | a integer primary key,
19 | b varchar(20) not null
20 | );
21 | insert or ignore into T1 values(1, 'abc');
22 | """)
23 |
24 | def tearDown(self):
25 | with db_session:
26 | conn = self.db.get_connection()
27 | conn.executescript("""drop table T1
28 | """)
29 |
30 | @db_session
31 | def test_alias(self):
32 | sql_ast = [SELECT, [ALL, [COLUMN, "Group", "a"]],
33 | [FROM, ["Group", TABLE, "T1" ]]]
34 | sql, adapter = self.db._ast2sql(sql_ast)
35 | cursor = self.db._exec_sql(sql)
36 | @db_session
37 | def test_alias2(self):
38 | sql_ast = [SELECT, [ALL, [COLUMN, None, "a"]],
39 | [FROM, [None, TABLE, "T1"]]]
40 | sql, adapter = self.db._ast2sql(sql_ast)
41 | cursor = self.db._exec_sql(sql)
42 |
43 |
44 | if __name__ == "__main__":
45 | unittest.main()
46 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_sqlite_shared_memory_db.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import threading
4 | import unittest
5 |
6 | from pony.orm.core import *
7 |
8 |
9 | db = Database('sqlite', ':sharedmemory:')
10 |
11 |
12 | class Person(db.Entity):
13 | name = Required(str)
14 |
15 | db.generate_mapping(create_tables=True)
16 |
17 | with db_session:
18 | Person(name='John')
19 | Person(name='Mike')
20 |
21 |
22 | class TestThread(threading.Thread):
23 | def __init__(self, *args, **kwargs):
24 | super().__init__(*args, *kwargs)
25 | self.result = []
26 | def run(self):
27 | with db_session:
28 | persons = Person.select().fetch()
29 | self.result.extend(p.name for p in persons)
30 |
31 |
32 | class TestFlush(unittest.TestCase):
33 | def test1(self):
34 | thread1 = TestThread()
35 | thread1.start()
36 | thread1.join()
37 | self.assertEqual(set(thread1.result), {'John', 'Mike'})
38 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_sqlite_str_functions.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | from __future__ import absolute_import, print_function, division
4 |
5 | from binascii import unhexlify
6 | import unittest
7 |
8 | from pony.orm.core import *
9 | from pony.orm.tests.testutils import *
10 | from pony.orm.tests import only_for
11 |
12 | db = Database('sqlite', ':memory:')
13 |
14 |
15 | class Person(db.Entity):
16 | name = Required(str)
17 | age = Optional(int)
18 | image = Optional(buffer)
19 |
20 |
21 | db.generate_mapping(create_tables=True)
22 |
23 | with db_session:
24 | p1 = Person(name='John', age=20, image=unhexlify('abcdef'))
25 | p2 = Person(name=u'Иван') # u'\u0418\u0432\u0430\u043d'
26 |
27 |
28 | @only_for('sqlite')
29 | class TestUnicode(unittest.TestCase):
30 | @db_session
31 | def test1(self):
32 | names = select(p.name for p in Person).order_by(lambda: p.id)[:]
33 | self.assertEqual(names, ['John', u'Иван'])
34 |
35 | @db_session
36 | def test2(self):
37 | names = select(p.name.upper() for p in Person).order_by(lambda: p.id)[:]
38 | self.assertEqual(names, ['JOHN', u'ИВАН']) # u'\u0418\u0412\u0410\u041d'
39 |
40 | @db_session
41 | def test3(self):
42 | names = select(p.name.lower() for p in Person).order_by(lambda: p.id)[:]
43 | self.assertEqual(names, ['john', u'иван']) # u'\u0438\u0432\u0430\u043d'
44 |
45 | @db_session
46 | def test4(self):
47 | ages = db.select('select py_upper(age) from person')
48 | self.assertEqual(ages, ['20', None])
49 |
50 | @db_session
51 | def test5(self):
52 | ages = db.select('select py_lower(age) from person')
53 | self.assertEqual(ages, ['20', None])
54 |
55 | @db_session
56 | def test6(self):
57 | ages = db.select('select py_upper(image) from person')
58 | self.assertEqual(ages, [u'ABCDEF', None])
59 |
60 | @db_session
61 | def test7(self):
62 | ages = db.select('select py_lower(image) from person')
63 | self.assertEqual(ages, [u'abcdef', None])
64 |
65 |
66 | if __name__ == '__main__':
67 | unittest.main()
68 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_tracked_value.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from pony.orm.ormtypes import TrackedList, TrackedDict, TrackedValue
4 |
5 | class Object(object):
6 | def __init__(self):
7 | self.on_attr_changed = None
8 | def _attr_changed_(self, attr):
9 | if self.on_attr_changed is not None:
10 | self.on_attr_changed(attr)
11 |
12 |
13 | class Attr(object):
14 | pass
15 |
16 |
17 | class TestTrackedValue(unittest.TestCase):
18 |
19 | def test_make(self):
20 | obj = Object()
21 | attr = Attr()
22 | value = {'items': ['one', 'two', 'three']}
23 | tracked_value = TrackedValue.make(obj, attr, value)
24 | self.assertEqual(type(tracked_value), TrackedDict)
25 | self.assertEqual(type(tracked_value['items']), TrackedList)
26 |
27 | def test_dict_setitem(self):
28 | obj = Object()
29 | attr = Attr()
30 | value = {'items': ['one', 'two', 'three']}
31 | tracked_value = TrackedValue.make(obj, attr, value)
32 | log = []
33 | obj.on_attr_changed = lambda x: log.append(x)
34 | tracked_value['items'] = [1, 2, 3]
35 | self.assertEqual(log, [attr])
36 |
37 | def test_list_append(self):
38 | obj = Object()
39 | attr = Attr()
40 | value = {'items': ['one', 'two', 'three']}
41 | tracked_value = TrackedValue.make(obj, attr, value)
42 | log = []
43 | obj.on_attr_changed = lambda x: log.append(x)
44 | tracked_value['items'].append('four')
45 | self.assertEqual(log, [attr])
46 |
47 | def test_list_setslice(self):
48 | obj = Object()
49 | attr = Attr()
50 | value = {'items': ['one', 'two', 'three']}
51 | tracked_value = TrackedValue.make(obj, attr, value)
52 | log = []
53 | obj.on_attr_changed = lambda x: log.append(x)
54 | tracked_value['items'][1:2] = ['a', 'b', 'c']
55 | self.assertEqual(log, [attr])
56 | self.assertEqual(tracked_value['items'], ['one', 'a', 'b', 'c', 'three'])
57 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_transaction_lock.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 |
4 | from pony.orm import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 | db = Database()
8 |
9 |
10 | class TestPost(db.Entity):
11 | category = Optional('TestCategory')
12 | name = Optional(str, default='Noname')
13 |
14 |
15 | class TestCategory(db.Entity):
16 | posts = Set(TestPost)
17 |
18 |
19 | class TransactionLockTestCase(unittest.TestCase):
20 | @classmethod
21 | def setUpClass(cls):
22 | setup_database(db)
23 | with db_session:
24 | cls.post = TestPost(id=1)
25 |
26 | @classmethod
27 | def tearDownClass(cls):
28 | teardown_database(db)
29 |
30 | __call__ = db_session(unittest.TestCase.__call__)
31 |
32 | def tearDown(self):
33 | rollback()
34 |
35 | def test_create(self):
36 | p = TestPost(id=2)
37 | p.flush()
38 | cache = db._get_cache()
39 | self.assertEqual(cache.immediate, True)
40 | self.assertEqual(cache.in_transaction, True)
41 |
42 | def test_update(self):
43 | p = TestPost[self.post.id]
44 | p.name = 'Trash'
45 | p.flush()
46 | cache = db._get_cache()
47 | self.assertEqual(cache.immediate, True)
48 | self.assertEqual(cache.in_transaction, True)
49 |
50 | def test_delete(self):
51 | p = TestPost[self.post.id]
52 | p.delete()
53 | flush()
54 | cache = db._get_cache()
55 | self.assertEqual(cache.immediate, True)
56 | self.assertEqual(cache.in_transaction, True)
57 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_validate.py:
--------------------------------------------------------------------------------
1 | import unittest, warnings
2 |
3 | from pony.orm import *
4 | from pony.orm import core
5 | from pony.orm.tests.testutils import raises_exception
6 | from pony.orm.tests import db_params, teardown_database
7 |
8 | db = Database()
9 |
10 | class Person(db.Entity):
11 | id = PrimaryKey(int)
12 | name = Required(str)
13 | tel = Optional(str)
14 |
15 |
16 | table_name = 'person'
17 |
18 | class TestValidate(unittest.TestCase):
19 | @classmethod
20 | def setUpClass(cls):
21 | db.bind(**db_params)
22 | db.generate_mapping(check_tables=False)
23 | db.drop_all_tables(with_all_data=True)
24 | with db_session(ddl=True):
25 | db.execute("""
26 | create table "%s"(
27 | id int primary key,
28 | name text,
29 | tel text
30 | )
31 | """ % table_name)
32 |
33 | @classmethod
34 | def tearDownClass(cls):
35 | teardown_database(db)
36 |
37 | @db_session
38 | def setUp(self):
39 | db.execute('delete from "%s"' % table_name)
40 | registry = getattr(core, '__warningregistry__', {})
41 | for key in list(registry):
42 | if type(key) is not tuple: continue
43 | text, category, lineno = key
44 | if category is DatabaseContainsIncorrectEmptyValue:
45 | del registry[key]
46 |
47 | @db_session
48 | def test_1a(self):
49 | with warnings.catch_warnings():
50 | warnings.simplefilter('ignore', DatabaseContainsIncorrectEmptyValue)
51 | db.insert(table_name, id=1, name='', tel='111')
52 | p = Person.get(id=1)
53 | self.assertEqual(p.name, '')
54 |
55 | @raises_exception(DatabaseContainsIncorrectEmptyValue,
56 | 'Database contains empty string for required attribute Person.name')
57 | @db_session
58 | def test_1b(self):
59 | with warnings.catch_warnings():
60 | warnings.simplefilter('error', DatabaseContainsIncorrectEmptyValue)
61 | db.insert(table_name, id=1, name='', tel='111')
62 | p = Person.get(id=1)
63 |
64 | @db_session
65 | def test_2a(self):
66 | with warnings.catch_warnings():
67 | warnings.simplefilter('ignore', DatabaseContainsIncorrectEmptyValue)
68 | db.insert(table_name, id=1, name=None, tel='111')
69 | p = Person.get(id=1)
70 | self.assertEqual(p.name, None)
71 |
72 | @raises_exception(DatabaseContainsIncorrectEmptyValue,
73 | 'Database contains NULL for required attribute Person.name')
74 | @db_session
75 | def test_2b(self):
76 | with warnings.catch_warnings():
77 | warnings.simplefilter('error', DatabaseContainsIncorrectEmptyValue)
78 | db.insert(table_name, id=1, name=None, tel='111')
79 | p = Person.get(id=1)
80 |
81 |
82 | if __name__ == '__main__':
83 | unittest.main()
84 |
--------------------------------------------------------------------------------
/pony/orm/tests/test_volatile.py:
--------------------------------------------------------------------------------
1 | import sys, unittest
2 |
3 | from pony.orm import *
4 | from pony.orm.tests.testutils import *
5 | from pony.orm.tests import setup_database, teardown_database
6 |
7 |
8 | class TestVolatile1(unittest.TestCase):
9 | def setUp(self):
10 | db = self.db = Database()
11 |
12 | class Item(self.db.Entity):
13 | name = Required(str)
14 | index = Required(int, volatile=True)
15 |
16 | setup_database(db)
17 |
18 | with db_session:
19 | Item(id=1, name='A', index=1)
20 | Item(id=2, name='B', index=2)
21 | Item(id=3, name='C', index=3)
22 |
23 | def tearDown(self):
24 | teardown_database(self.db)
25 |
26 | @db_session
27 | def test_1(self):
28 | db = self.db
29 | Item = db.Item
30 | db.execute('update "item" set "index" = "index" + 1')
31 | items = Item.select(lambda item: item.index > 0).order_by(Item.id)[:]
32 | a, b, c = items
33 | self.assertEqual(a.index, 2)
34 | self.assertEqual(b.index, 3)
35 | self.assertEqual(c.index, 4)
36 | c.index = 1
37 | items = Item.select()[:] # force re-read from the database
38 | self.assertEqual(c.index, 1)
39 | self.assertEqual(a.index, 2)
40 | self.assertEqual(b.index, 3)
41 |
42 |
43 | @db_session
44 | def test_2(self):
45 | Item = self.db.Item
46 | item = Item[1]
47 | item.name = 'X'
48 | item.flush()
49 | self.assertEqual(item.index, 1)
50 |
51 |
52 | class TestVolatile2(unittest.TestCase):
53 | def setUp(self):
54 | db = self.db = Database()
55 |
56 | class Group(db.Entity):
57 | number = PrimaryKey(int)
58 | students = Set('Student', volatile=True)
59 |
60 | class Student(db.Entity):
61 | id = PrimaryKey(int)
62 | name = Required(str)
63 | group = Required('Group')
64 | courses = Set('Course')
65 |
66 | class Course(db.Entity):
67 | id = PrimaryKey(int)
68 | name = Required(str)
69 | students = Set('Student', volatile=True)
70 |
71 | setup_database(db)
72 |
73 | with db_session:
74 | g1 = Group(number=123)
75 | s1 = Student(id=1, name='A', group=g1)
76 | s2 = Student(id=2, name='B', group=g1)
77 | c1 = Course(id=1, name='C1', students=[s1, s2])
78 | c2 = Course(id=2, name='C1', students=[s1])
79 |
80 | self.Group = Group
81 | self.Student = Student
82 | self.Course = Course
83 |
84 | def tearDown(self):
85 | teardown_database(self.db)
86 |
87 | def test_1(self):
88 | self.assertTrue(self.Group.students.is_volatile)
89 | self.assertTrue(self.Student.group.is_volatile)
90 | self.assertTrue(self.Student.courses.is_volatile)
91 | self.assertTrue(self.Course.students.is_volatile)
92 |
93 | def test_2(self):
94 | with db_session:
95 | g1 = self.Group[123]
96 | students = set(s.id for s in g1.students)
97 | self.assertEqual(students, {1, 2})
98 | self.db.execute('''insert into student values(3, 'C', 123)''')
99 | g1.students.load()
100 | students = set(s.id for s in g1.students)
101 | self.assertEqual(students, {1, 2, 3})
102 |
103 | def test_3(self):
104 | with db_session:
105 | g1 = self.Group[123]
106 | students = set(s.id for s in g1.students)
107 | self.assertEqual(students, {1, 2})
108 | self.db.execute("insert into student values(3, 'C', 123)")
109 | s3 = self.Student[3]
110 | students = set(s.id for s in g1.students)
111 | self.assertEqual(students, {1, 2, 3})
112 |
113 | def test_4(self):
114 | with db_session:
115 | c1 = self.Course[1]
116 | students = set(s.id for s in c1.students)
117 | self.assertEqual(students, {1, 2})
118 | self.db.execute("insert into student values(3, 'C', 123)")
119 | attr = self.Student.courses
120 | self.db.execute("insert into %s values(1, 3)" % attr.table)
121 | c1.students.load()
122 | students = set(s.id for s in c1.students)
123 | self.assertEqual(students, {1, 2, 3})
124 |
125 |
126 | if __name__ == '__main__':
127 | unittest.main()
128 |
--------------------------------------------------------------------------------
/pony/orm/tests/testutils.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, print_function, division
2 |
3 | import re
4 | from contextlib import contextmanager
5 |
6 | from pony.orm.core import Database
7 | from pony.utils import import_module
8 |
9 | def check_exception_msg(test_case, exc_msg, test_msg=None):
10 | if test_msg is None: return
11 | error_template = "incorrect exception message. expected '%s', got '%s'"
12 | error_msg = error_template % (test_msg, exc_msg)
13 | assert test_msg not in ('...', '....', '.....', '......')
14 | if '...' not in test_msg:
15 | test_case.assertEqual(test_msg, exc_msg, error_msg)
16 | else:
17 | pattern = ''.join(
18 | '[%s]' % char for char in test_msg.replace('\\', '\\\\')
19 | .replace('[', '\\[')
20 | ).replace('[.][.][.]', '.*')
21 | regex = re.compile(pattern)
22 | if not regex.match(exc_msg):
23 | test_case.fail(error_template % (test_msg, exc_msg))
24 |
25 | def raises_exception(exc_class, test_msg=None):
26 | def decorator(func):
27 | def wrapper(test_case, *args, **kwargs):
28 | try:
29 | func(test_case, *args, **kwargs)
30 | test_case.fail("Expected exception %s wasn't raised" % exc_class.__name__)
31 | except exc_class as e:
32 | if not e.args: test_case.assertEqual(test_msg, None)
33 | else: check_exception_msg(test_case, str(e), test_msg)
34 | wrapper.__name__ = func.__name__
35 | return wrapper
36 | return decorator
37 |
38 | @contextmanager
39 | def raises_if(test_case, cond, exc_class, test_msg=None):
40 | try:
41 | yield
42 | except exc_class as e:
43 | test_case.assertTrue(cond)
44 | check_exception_msg(test_case, str(e), test_msg)
45 | else:
46 | test_case.assertFalse(cond, "Expected exception %s wasn't raised" % exc_class.__name__)
47 |
48 | def flatten(x):
49 | result = []
50 | for el in x:
51 | if hasattr(el, "__iter__") and not isinstance(el, str):
52 | result.extend(flatten(el))
53 | else:
54 | result.append(el)
55 | return result
56 |
57 | class TestConnection(object):
58 | def __init__(con, database):
59 | con.database = database
60 | if database and database.provider_name == 'postgres':
61 | con.autocommit = True
62 | def commit(con):
63 | pass
64 | def rollback(con):
65 | pass
66 | def cursor(con):
67 | return test_cursor
68 |
69 | class TestCursor(object):
70 | def __init__(cursor):
71 | cursor.description = []
72 | cursor.rowcount = 0
73 | def execute(cursor, sql, args=None):
74 | pass
75 | def fetchone(cursor):
76 | return None
77 | def fetchmany(cursor, size):
78 | return []
79 | def fetchall(cursor):
80 | return []
81 |
82 | test_cursor = TestCursor()
83 |
84 | class TestPool(object):
85 | def __init__(pool, database):
86 | pool.database = database
87 | def connect(pool):
88 | return TestConnection(pool.database), True
89 | def release(pool, con):
90 | pass
91 | def drop(pool, con):
92 | pass
93 | def disconnect(pool):
94 | pass
95 |
96 | class TestDatabase(Database):
97 | real_provider_name = None
98 | raw_server_version = None
99 | sql = None
100 | def bind(self, provider, *args, **kwargs):
101 | provider_name = provider
102 | assert isinstance(provider_name, str)
103 | if self.real_provider_name is not None:
104 | provider_name = self.real_provider_name
105 | self.provider_name = provider_name
106 | provider_module = import_module('pony.orm.dbproviders.' + provider_name)
107 | provider_cls = provider_module.provider_cls
108 | raw_server_version = self.raw_server_version
109 |
110 | if raw_server_version is None:
111 | if provider_name == 'sqlite': raw_server_version = '3.7.17'
112 | elif provider_name in ('postgres', 'pygresql'): raw_server_version = '9.2'
113 | elif provider_name == 'oracle': raw_server_version = '11.2.0.2.0'
114 | elif provider_name == 'mysql': raw_server_version = '5.6.11'
115 | else: assert False, provider_name # pragma: no cover
116 |
117 | t = [ int(component) for component in raw_server_version.split('.') ]
118 | if len(t) == 2: t.append(0)
119 | server_version = tuple(t)
120 | if provider_name in ('postgres', 'pygresql'):
121 | server_version = int('%d%02d%02d' % server_version)
122 |
123 | class TestProvider(provider_cls):
124 | json1_available = False # for SQLite
125 | def inspect_connection(provider, connection):
126 | pass
127 | TestProvider.server_version = server_version
128 |
129 | kwargs['pony_check_connection'] = False
130 | kwargs['pony_pool_mockup'] = TestPool(self)
131 | Database.bind(self, TestProvider, *args, **kwargs)
132 | def _execute(database, sql, globals, locals, frame_depth):
133 | assert False # pragma: no cover
134 | def _exec_sql(database, sql, arguments=None, returning_id=False):
135 | assert type(arguments) is not list and not returning_id
136 | database.sql = sql
137 | database.arguments = arguments
138 | return test_cursor
139 | def generate_mapping(database, filename=None, check_tables=True, create_tables=False):
140 | return Database.generate_mapping(database, filename, create_tables=False, check_tables=False)
141 |
--------------------------------------------------------------------------------
/pony/py23compat.py:
--------------------------------------------------------------------------------
1 | import sys, platform
2 |
3 | PYPY = platform.python_implementation() == 'PyPy'
4 | PY36 = sys.version_info[:2] >= (3, 6)
5 | PY37 = sys.version_info[:2] >= (3, 7)
6 | PY38 = sys.version_info[:2] >= (3, 8)
7 | PY39 = sys.version_info[:2] >= (3, 9)
8 | PY310 = sys.version_info[:2] >= (3, 10)
9 | PY311 = sys.version_info[:2] >= (3, 11)
10 | PY312 = sys.version_info[:2] >= (3, 12)
11 |
12 | unicode = str
13 | buffer = bytes
14 | int_types = (int,)
15 |
16 | def cmp(a, b):
17 | return (a > b) - (a < b)
18 |
--------------------------------------------------------------------------------
/pony/thirdparty/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ponyorm/pony/b9375605edacde9e68e3fc5c578a4b090a36cb8d/pony/thirdparty/__init__.py
--------------------------------------------------------------------------------
/pony/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | from .utils import *
4 | from .properties import *
--------------------------------------------------------------------------------
/pony/utils/properties.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | class cached_property(object):
4 | """
5 | A property that is only computed once per instance and then replaces itself
6 | with an ordinary attribute. Deleting the attribute resets the property.
7 | Source: https://github.com/bottlepy/bottle/commit/fa7733e075da0d790d809aa3d2f53071897e6f76
8 | """ # noqa
9 |
10 | def __init__(self, func):
11 | self.__doc__ = getattr(func, '__doc__')
12 | self.func = func
13 |
14 | def __get__(self, obj, cls):
15 | if obj is None:
16 | return self
17 | value = obj.__dict__[self.func.__name__] = self.func(obj)
18 | return value
19 |
20 |
21 | class class_property(object):
22 | """
23 | Read-only class property
24 | """
25 |
26 | def __init__(self, func):
27 | self.func = func
28 |
29 | def __get__(self, instance, cls):
30 | return self.func(cls)
31 |
32 | class class_cached_property(object):
33 |
34 | def __init__(self, func):
35 | self.func = func
36 |
37 | def __get__(self, obj, cls):
38 | value = self.func(cls)
39 | setattr(cls, self.func.__name__, value)
40 | return value
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 |
3 | from setuptools import setup
4 | import sys
5 |
6 | import unittest
7 |
8 | def test_suite():
9 | test_loader = unittest.TestLoader()
10 | test_suite = test_loader.discover('pony.orm.tests', pattern='test_*.py')
11 | return test_suite
12 |
13 | name = "pony"
14 | version = __import__('pony').__version__
15 | description = "Pony Object-Relational Mapper"
16 | long_description = """
17 | About
18 | =========
19 | Pony ORM is easy to use and powerful object-relational mapper for Python.
20 | Using Pony, developers can create and maintain database-oriented software applications
21 | faster and with less effort. One of the most interesting features of Pony is
22 | its ability to write queries to the database using generator expressions.
23 | Pony then analyzes the abstract syntax tree of a generator and translates it
24 | to its SQL equivalent.
25 |
26 | Following is an example of a query in Pony::
27 |
28 | select(p for p in Product if p.name.startswith('A') and p.cost <= 1000)
29 |
30 | Such approach simplify the code and allows a programmer to concentrate
31 | on the business logic of the application.
32 |
33 | Pony translates queries to SQL using a specific database dialect.
34 | Currently Pony works with SQLite, MySQL, PostgreSQL and Oracle databases.
35 |
36 | The package `pony.orm.examples `_
37 | contains several examples.
38 |
39 | Installation
40 | =================
41 | ::
42 |
43 | pip install pony
44 |
45 | Entity-Relationship Diagram Editor
46 | =============================================
47 | `Pony online ER Diagram Editor `_ is a great tool for prototyping.
48 | You can draw your ER diagram online, generate Pony entity declarations or SQL script for
49 | creating database schema based on the diagram and start working with the database in seconds.
50 |
51 | Pony ORM Links:
52 | =================
53 | - Main site: https://ponyorm.com
54 | - Documentation: https://docs.ponyorm.com
55 | - GitHub: https://github.com/ponyorm/pony
56 | - Mailing list: http://ponyorm-list.ponyorm.com
57 | - ER Diagram Editor: https://editor.ponyorm.com
58 | - Blog: https://blog.ponyorm.com
59 | """
60 |
61 | classifiers = [
62 | 'Development Status :: 4 - Beta',
63 | 'Intended Audience :: Developers',
64 | 'License :: OSI Approved :: Apache Software License',
65 | 'Operating System :: OS Independent',
66 | 'Programming Language :: Python',
67 | 'Programming Language :: Python :: 3',
68 | 'Programming Language :: Python :: 3.8',
69 | 'Programming Language :: Python :: 3.9',
70 | 'Programming Language :: Python :: 3.10',
71 | 'Programming Language :: Python :: 3.11',
72 | 'Programming Language :: Python :: 3.12',
73 | 'Programming Language :: Python :: Implementation :: PyPy',
74 | 'Topic :: Software Development :: Libraries',
75 | 'Topic :: Database'
76 | ]
77 |
78 | author = ', '.join([
79 | 'Alexander Kozlovsky ',
80 | 'Alexey Malashkevich ',
81 | 'Alexander Tischenko '
82 | ])
83 | author_email = "team@ponyorm.com"
84 | url = "https://ponyorm.com"
85 | project_urls = {
86 | "Documentation": "https://docs.ponyorm.org",
87 | "Source": "https://github.com/ponyorm/pony",
88 | }
89 | licence = "Apache License Version 2.0"
90 |
91 | packages = [
92 | "pony",
93 | "pony.flask",
94 | "pony.flask.example",
95 | "pony.orm",
96 | "pony.orm.dbproviders",
97 | "pony.orm.examples",
98 | "pony.orm.integration",
99 | "pony.orm.tests",
100 | "pony.thirdparty",
101 | "pony.utils"
102 | ]
103 |
104 | package_data = {
105 | 'pony.flask.example': ['templates/*.html'],
106 | 'pony.orm.tests': ['queries.txt']
107 | }
108 |
109 | download_url = "http://pypi.python.org/pypi/pony/"
110 |
111 | if __name__ == "__main__":
112 | pv = sys.version_info[:2]
113 | if pv < (3, 8) or pv > (3, 12):
114 | s = "Sorry, but %s %s requires Python of one of the following versions: 3.8-3.12." \
115 | " You have version %s"
116 | print(s % (name, version, sys.version.split(' ', 1)[0]))
117 | sys.exit(1)
118 |
119 | setup(
120 | name=name,
121 | version=version,
122 | description=description,
123 | long_description=long_description,
124 | classifiers=classifiers,
125 | author=author,
126 | author_email=author_email,
127 | url=url,
128 | project_urls=project_urls,
129 | license=licence,
130 | packages=packages,
131 | package_data=package_data,
132 | download_url=download_url,
133 | test_suite='setup.test_suite'
134 | )
135 |
--------------------------------------------------------------------------------