Author: Kale (kryogenic) Date: Thu Oct 10 11:16 AM 2024 +0000
- privex.helpers.cache
- Replaced
aioredis
with redis 4.2.0 (breaks Python<3.6)
- Replaced
Author: Chris (Someguy123) Date: Mon Nov 2 03:26 AM 2020 +0000
-
privex.helpers.settings
-
Added
DEFAULT_CACHE_ADAPTER
which can be adjusted via the env varPRIVEX_CACHE_ADAPTER
. This setting allows overriding the cache adapter which is used automatically by default viacached
/async_cached
, along with the global adapter when you callget_adapter
-
Added
DEFAULT_ASYNC_CACHE_ADAPTER
which can be adjusted via the env varPRIVEX_ASYNC_CACHE_ADAPTER
. It defaults to the same value asDEFAULT_CACHE_ADAPTER
, since thanks to the newimport_adapter
function andADAPTER_MAP
dictionary inprivex.helpers.cache
, it's now possible to reference cache adapters by simple names such asmemcached
,redis
,sqlite3
,memory
etc. - and these aliases point to either the synchronous or asyncio version of their related adapter depending on which context they're being passed into.
-
-
privex.helpers.cache
-
Added
MemcachedCache
module, which contains the synchronous cache adapterMemcachedCache
. This is simply a synchronous version ofAsyncMemcachedCache
that usespylibmc
instead ofaiomcache
. -
Added
ADAPTER_MAP
dictionary, which maps aliases such asmemcached
,redis
,sqlite3
,memory
etc. to their respective synchronous and asyncio adapter module paths, which can be loaded using the newly addedimport_adapter
function, or simply usingadapter_set
/async_adapter_set
. -
Added
import_adapter
function, which looks up an adapter alias name such asredis
/memcached
, maps it to the fully qualified module path viaADAPTER_MAP
, and then loads the module + extracts the class from the module. -
Adjusted
adapter_set
,async_adapter_set
, along withCacheWrapper
+AsyncCacheWrapper
so that they now use the default string cache adapter defined insettings
, and can transparently handle string adapter values by passing them off toimport_adapter
. -
Added new
extras
module-
CacheManagerMixin
is a class mixin which adds various methods and settings to assist with class-scoped caching, including an adjustable class-level cache prefix.cache_prefix
, a method to remove all known cache keys managed by your class.clear_all_cache_keys
, and a special decorator which automatically integrates with your class.z_cache
by intercepting the first argument of a method call. -
z_cache
- A special method caching decorator which is designed to integrate with classes that extend.CacheManagerMixin
This is simply a wrapper for
.r_cache
- it transparently caches the output of a wrapped method/function, but unlike.r_cache
, it's designed to automatically integrate with classes which extend.CacheManagerMixin
, allowing it to automatically retrieve cache settings such as the cache prefix, default cache time, along with directly calling various classmethods which enable logging of newly createdcache_key
's for painless cleanup of cache keys when needed, without having to manually track them, or doing the nuclear option of erasing the entire cache system's database.
-
-
-
privex.helpers.common
- Added new small helper function
auto_list
, which is a small but useful function that simplifies the conversion of objects into lists, sets, tuples etc. with the option to manually force a certain conversion method, eitherlist wrapping
orlist iteration
- Added new small helper function
-
privex.helpers.plugin
- Added various functions for managing memcached instances via the
pylibmc
libraryconnect_memcached
- create a new memcachedClient
objectget_memcached
- get or create a MemcachedClient
object shared by your threadclose_memcached
- close the MemcachedClient
connection and delete it from the threadstorereset_memcached
- close the sharedClient
then re-create it again.configure_memcached
- configure Memcached settings then automatically reset the sharedClient
instance.
- Added new
HAS_MEMCACHED
boolean value, to track whether synchronous memcached viapylibmc
is available
- Added various functions for managing memcached instances via the
-
General stuff
- Added
pylibmc
to extras/cache.txt - Added some missing packages to the
Pipfile
- and synchronisedPipfile.lock
- Added
.env
to.gitignore
- Created unit tests for the new
CacheManagerMixin
class andz_cache
decorator - Created unit tests for the new
MemcachedCache
cache adapter - Fixed the
live
command indocs/Makefile
for newersphinx-autobuild
- Added
SqliteCache
andMemcachedCache
to the docs - Added
privex.helpers.cache.extras
andprivex.helpers.cache.post_dep
to the docs - Added some other missing things to the docs
- Created and updated a lot of stub files in
privex_stubs
(assists IDEs like PyCharm with type hinting and function/method previews) - Possibly other various additions / fixes / improvements that I forgot to list.
- Added
Author: Chris (Someguy123) Date: Wed Oct 7 11:36 2020 +0000
-
privex.helpers.cache
-
Added
SqliteCache
module, containing the synchronous cache adapterSqliteCache
which uses an Sqlite3 database for persistent cache storage without the need for any extra system service (unlike the memcached / redis adapters) -
Added
asyncx.AsyncSqliteCache
module, containing the AsyncIO cache adapterAsyncSqliteCache
, which is simply an AsyncIO version ofSqliteCache
using theaiosqlite
library.- NOTE: Due to the file-based nature of SQLite3, combined with the fact write operations generally result in the database being locked until the write is completed - use of the AsyncIO SQLite3 cache adapter only slightly improves performance, due to the blocking single-user nature of SQLite3.
-
Added
post_deps
module, short for post-init dependencies. This module contains functions and classes which are known to have (or have a high risk of) recursive import conflicts - e.g. the new SQLite caching uses theprivex-db
package, and theprivex-db
package imports various things fromprivex.helpers
causing a recursive import issue if we loadprivex.db
within a class that's auto-loaded in an__init__.py
file.The nature of this module means that none of it's contents are auto-loaded / aliased using
__init__.py
module constructor files. This shouldn't be a problem for most people though, as the functions/classes etc. within the module are primarily only useful for certain cache adapter classes, rather than intended for use by the users ofprivex-helpers
(though there's nothing stopping you from importing things frompost_deps
in your own project).sqlite_cache_set_dbfolder
andsqlite_cache_set_dbname
are two module level functions that are intended for use by users. These functions allow you to quickly override theDEFAULT_DB_FOLDER
and/orDEFAULT_DB_NAME
dynamically for both SqliteCacheManager and AsyncSqliteCacheManager.SqliteCacheResult
is a namedtuple that represents a row returned when querying thepvcache
table within an SQLite cache database_SQManagerBase
is a mix-in class used by bothSqliteCacheManager
andAsyncSqliteCacheManager
, containing code which is used by both classes.SqliteCacheManager
is a child class ofSqliteWrapper
, designed to provide easier interaction with an SQLite3 cache database, including automatic creation of the database file, and thepvcache
table within it. This class is intended for use byprivex.helpers.cache.SqliteCache
AsyncSqliteCacheManager
is a child class ofSqliteAsyncWrapper
, and is simply an AsyncIO version ofSqliteCacheManager
. This class is intended for use byprivex.helpers.cache.asyncx.AsyncSqliteCache
-
-
privex.helpers.plugins
- Added
HAS_PRIVEX_DB
attribute, for tracking whether theprivex-db
library is available for use. - Added
clean_threadstore
to__all__
- seems I forgot to add it previously.
- Added
-
privex.helpers.settings
- Added
SQLITE_APP_DB_NAME
which can also be controlled via an env var of the same name - allowing you to adjust the base of the default DB filename for the SQLite3 cache adapters. - Added
SQLITE_APP_DB_FOLDER
(can also be controlled via env) - similar to the DB_NAME attribute, controls the default base folder used by the SQLite3 cache adapters.
- Added
3.0.0 - Overhauled net module, new object cleaner for easier serialisation, improved class generation/mocking + more
Author: Chris (Someguy123) Date: Sat Sep 26 04:29 2020 +0000
-
privex.helpers.common
- Added
strip_null
- very simple helper function to strip both\00
and white space from a string - with 2 cycles for good measure.
- Added
-
privex.helpers.types
- Added
AUTO
/AUTOMATIC
/AUTO_DETECTED
dummy type, for use as the default value of function/method parameters, signalling to users that a parameter is auto-populated from another data source (e.g. instance/class attribute) if not specified.
- Added
-
privex.helpers.collections
- Added
copy_class_simple
(alternative tocopy_class
) - Added
copy_func
for copying functions, methods, and classmethods - Improved
_q_copy
to handle copying functions, methods and classmethods - Added
generate_class
+generate_class_kw
- Added
Mocker.make_mock_module
- Added
Mocker.add_mock_modules
- Added
Mocker.__dir__
to track the available mock attributes and modules - Added
dataclasses_mock
- aMocker
instance which emulatesdataclasses
as a drop-in partially functional dummy for Python 3.6 when thedataclasses
backport package isn't installed. - Various changes to
Mocker.make_mock_class
- potentially breaking, see the BREAKING CHANGES section. - Added
DictObject.__dir__
+OrderedDictObject.__dir__
to enable proper tracking of dictionary keys as attributes
- Added
-
privex.helpers.net
-
This module has now been converted into a folder-based module. Imports in
__init__.py
have been carefully setup to ensure that existing import statements should still work as normal -
Added new
SocketWrapper
andAsyncSocketWrapper
classes, which are powerful wrapper classes for working with Pythonsocket.socket
objects, including support for SSL/TLS, partial support for running socket servers, and
making basic HTTP requests -
Many, many new functions and classes! There's too many to list, and due to the conversion into a module folder instead of a singular file, it's difficult to track which functions/classes are new, and which existed before.
If you really want to know what's new, just take a look around the
privex/helpers/net
module.
-
-
privex.helpers.converters
- Added
clean_obj
- which is a function that recursively "cleans" any arbitrary object, as to make it safe to convert into JSON and other common serialisation formats. It supportsdict
's,list
's, attrs objects, native Pythondataclass
's,Decimal
, and many other types of objects. - Added
clean_dict
(used byclean_obj
, usually no need to call it directly) - Added
clean_list
(used byclean_obj
, usually no need to call it directly)
- Added
-
Added
privex.helpers.mockers
module, which contains pre-madeMocker
objects that are designed to stand-in for certain libraries / classes as partially functional dummies, if the real module(s) are unavailable for whatever reason. -
And probably some other small additions / changes
BREAKING CHANGES
-
Both
_copy_class_dict
and_copy_class_slotted
now check each attribute name against a blacklist (default:COPY_CLASS_BLACKLIST
), and the default blacklist contains__dict__
,__slots__
and__weakref__
, as the first 2 can't be directly copied (but we copy their contents by iteration), and weakref simply can't be deep copied (and it probably isn't a good idea to copy it anyway). -
_copy_class_dict
(used bycopy_class
) no longer breaks the attribute copy loop ifdeep_copy=False
-
Mocker.make_mock_class
now returns a clonedMocker
class or instance by default, instead of a barebones class / instance of a barebones class.This was done simply because a Mocker class/instance is designed to handle being instantiated with any combination of constructor arguments, and have arbitrary attributes be retrieved / methods called without raising errors.
If you absolutely require a plain, simple, empty class to be generated, you may pass the parameter
simple=True
to generate a bare class instead of a clone of Mocker (similar to the old behaviour). Unlike the old version of this method, you can now specify attributes as a dictionary to make your barebones mock class act similar to the class it's mocking. -
Many things in
privex.helpers.net
such ascheck_host
/check_host_async
have been improved in various ways, however there may be some breaking changes with certainprivex.helpers.net
functions/classes in certain usecases.-
Due to the high risk of bugs with certain networking functions that have been completely revamped, the older, simpler versions of various networking functions are available under
privex.helpers.net.base
with their original names.Because of the naming conflicts, to use the legacy functions/classes from
base
, you must import them directly fromprivex.helpers.net.base
like so:# Option 1: import the base module itself, with an alias to prevent naming conflicts (and make it more # clear what you're referencing) from privex.helpers.net import base as netbase if netbase.check_host('google.com', 80): print('google.com is up') # Option 2: import the required legacy functions directly (optionally, you can alias them as needed) # You could also alias the newer overhauled functions while testing them in small portions # of your application. from privex.helpers.net.base import check_host from privex.helpers.net import check_host as new_check_host if check_host('www.privex.io', 443, http_test=True, use_ssl=True): print('[old check_host] https://www.privex.io is up') if new_check_host('files.privex.io', 443, http_test=True, use_ssl=True): print('[new check_host] https://files.privex.io is up')
-
Author: Chris (Someguy123) Date: Tue 17 Dec 2019
Tl;Dr; important changes
- Added asyncx functions:
loop_run
,is_async_context
,_awaitable_blacklisted
- Added asyncx decorator
awaitable_class
, and mixin classAwaitableMixin
(mixin version of awaitable_class decorator) - Removed class
helpers.extras.git.Git
and replaced it with an alias toAsyncGit
as@awaitable_class
rendered the wrapper class obsolete - Refactored some types from
common
module intotypes
- Refactored tests and added some new tests for some of the added functions/classes
- Various refactoring and general cleanup
New Features / Additions
-
asyncx.loop_run
is similar toasyncx.run_sync
, but more flexible, and doesn't use the deprecatedasyncio.coroutine
function. It can be passed either a coroutine directly for execution, or if a function/method is passed, (doesn't have to be async) then it can attempt to extract the coroutine by calling each layer until a coroutine or non-callable is found.While there's no plan to remove
asynx.run_sync
in the near future, it's strongly recommended to switch usages ofrun_sync
toloop_run
because it's better at handling different forms of awaitable objects:-
Unlike
run_sync
, loop_run can handle both async function references AND coroutines -
Unlike
run_sync
, loop_run can unwrap coroutines / async function references that are wrapped in a normal non-async function (e.g.@awaitable
wrapper functions) -
Unlike
run_sync
, loop_run can accept the optional_loop
keyword argument, allowing you to specify a custom asyncio event loop if you desire. -
Unlike
run_sync
, loop_run will cleanly execute non-async functions if they're encountered, and simply return non-callable objects that were passed to it, instead of failing.
-
-
New function / class decorator
asyncx.awaitable_class
- wraps a class and overrides__getattribute__
to enable all async methods to be called from non-async code. Similar toasyncx.awaitable
, but affects all async methods in a class, and doesn't require non-async wrapper functions to be written.-
If a non-async method or standard attribute is requested, then those are returned as normal without modification.
-
If an async method is called on the class, then it checks to see if there's a current AsyncIO context - if there is, it simply returns the coroutine for
await
'ing -
If there isn't an async context, it will use
loop_run
to call the method synchronously using the current event loop, and return the method's result synchronously.
-
-
New class
asyncx.AwaitableMixin
- a mixin class which works the same asasyncx.awaitable_class
, but as a mixin class add to your class's inheritance, instead of a decorator. -
Created the file
CHANGELOG.md
- note that it doesn't contain a full changelog yet, it only goes back as far as version 2.5
Changes / Updates
-
The wrapper class
helpers.extras.git.Git
has been removed, asAsyncGit
now uses the much simpler@awaitable_class
decorator to enable synchronous usage of all async methods, instead of a sub-class with individually@awaitable
wrapped methods.To avoid breaking any existing code which relied on
extras.git.Git
,Git
is now an alias forAsyncGit
. No changes needed to be made to the Git tests intests/test_extras.py
, so this change isn't believed to cause code breakage. -
A large portion of the decorator
asyncx.awaitable
has been refactored into the smaller functions:_awaitable_blacklisted
andis_async_context
. -
During the refactoring of
asyncx.awaitable
, a bug was discovered in the blacklist scanning for sub-modules - this is now fixed (note: blacklist scanning is refactored into_awaitable_blacklisted
) -
asyncx.py
now has an__all__
module attribute, allowing__init__
to simply import*
instead of having to list each class/function etc. -
cache.asyncx.__init__
-
Added a PyDoc comment at the start of the file, explaining the AsyncIO adapters and how to use them.
-
Added the attributes
HAS_ASYNC_REDIS
,HAS_ASYNC_MEMORY
, andHAS_ASYNC_MEMCACHED
to allow for easy availability checking of async cache adapters. -
Lowered the
ImportError
log level for AsyncRedisCache and AsyncMemcachedCache fromlog.exception
down tolog.debug
-
-
Refactored various generic / template types (e.g.
T
,K
,CL
) fromhelpers.common
intohelpers.types
Testing
-
Refactored
tests/test_general.py
into a foldertests/general/
-
Refactored AsyncIO related tests from
tests/test_general.py
intotests/asyncx/test_async_common.py
-
Added several new AsyncIO tests to
tests/asyncx/test_async_common.py
, mainly aimed at the newasyncx.awaitable_class
, andasyncx.AwaitableMixin
Author: Chris (Someguy123) Date: Fri Dec 13 09:16:57 2019 +0000
New Features / Additions
-
privex.helpers.common
- Added
extract_settings
for extracting prefixed settings from modules, classes or dict's.
- Added
-
Created new
helpers.black_magic
module for somewhat risky code that uses app introspectioncalling_function
- Returns the name of the function which called your function/method.calling_module
- Returns the name of the module which called your function/methodcaller_name
- Get the fully qualified name of a caller in the formatsome.module.SomeClass.method
-
Created new
helpers.types
module for holding type aliases and new type definitions -
privex.helpers.decorators
- Added
async_retry
decorator, which works similar toretry_on_error
, but supports wrapping asyncio coroutines
- Added
-
privex.helpers.cache
- Created new
asyncx
submodule for AsyncIO cache adapters asyncx.base.AsyncCacheAdapter
is a new base class for AsyncIO cache adapters, with all methods as corosasyncx.AsyncRedisCache
is a new AsyncIO cache adapter for Redisasyncx.AsyncMemoryCache
is a new AsyncIO cache adapter for in-memory caching (async version ofMemoryCache
)asyncx.AsyncMemcachedCache
is a new AsyncIO cache adapter for MemcachedCacheAdapter
has a new methodget_or_set_async
, which is an async method that supports coroutines as a value, as well as standard callable's and plain values
- Created new
-
privex.helpers.plugin
- New functions for organising __STORE by thread:
_get_threadstore
,_set_threadstore
,clean_threadstore
- New functions for managing AsyncIO Redis (aioredis) instances
get_redis_async
,close_redis_async
etc. - New functions for managing AsyncIO Memcached (aiomcache) instances
get_memcached_async
,close_memcached_async
etc.
- New functions for organising __STORE by thread:
Changes / Updates
-
Added
aioredis
,hiredis
, andaiomcache
toextras/cache.txt
-
async-property
is now a core requirement, since it's used by a lot of async classes -
New settings
MEMCACHED_HOST
andMEMCACHED_PORT
for AsyncMemcachedCache -
New plugin status
HAS_ASYNC_REDIS
for detecting ifaioredis
is available -
privex.helpers.decorators
retry_on_err
has been slightly cleaned upretry_on_err
now supports ignoring exceptions, so you can list exceptions that cause a retry, but shouldn't increase the retry count.retry_on_err
now supports the settinginstance_match
, which changes how exceptions are compared. When enabled, it will compare usingisinstance()
instead of an exact type comparison.
-
privex.helpers.asyncx
awaitable
decorator now detects when it's received a non-async function, and returns the result correctlyawaitable
now supports "blacklisting" functions/modules, to ensure when those functions/modules call an@awaitable
function, that they always get a synchronous result, not a coroutine.
-
privex.helpers.cache
CacheWrapper
now uses@awaitable
for most methods, allowing AsyncIO cache adapters to be used without breaking existing synchronous code which uses the cache API.CacheAdapter
now has dummy__enter__
and__exit__
methods defined, allowing all synchronous cache adapters to be used in awith
statement, regardless of whether they actually use context management.
-
privex.helpers.plugin
get_redis
,close_redis
,reset_redis
etc. now use the new thread store system to help ensure thread safety by separating instances per thread.- Refactored
get_redis
's connection opening intoconnect_redis
, and now usesextract_settings
for loading default settings
Testing
-
Added unit tests for
extract_settings
totests/test_general.py
-
New folders
tests/asyncx
andtests/cache
for containing flat test case modules using pytest-asyncio -
tests/asyncx/test_async_retry.py
tests the new@async_retry
decorator -
tests/cache/test_async_memcached.py
tests the newAsyncMemcachedCache
class -
tests/cache/test_async_redis.py
tests the newAsyncRedisCache
class -
tests/cache/test_async_memory.py
tests the newAsyncMemoryCache
class
Additional merged commits:
- enable memcached on travis
Author: Chris (Someguy123) Date: Sat Dec 7 05:57:20 2019 +0000
- Created
helpers.extras.git
module, which contains a git command wrapper that works with both sync and async functions- Primarily intended for the three methods:
get_current_commit
,get_current_branch
, andget_current_tag
, which allows python applications and libraries to identify what version they are, via git. - Includes various basic methods such as
init
,checkout
,branch
,tag
,status
,log
and others.
- Primarily intended for the three methods:
- Added new async helpers
aobject
allows sub-classes to haveasync __init__
constructorsawaitable
helps create wrapper functions that allow async functions to work with sync code seamlessly
- Improved
byteify
andstringify
with None handling - Added new
SysCallError
exception sniffio
is now a required dependency - however it's very small and dependency free in itself (only about 30kb).- Added unit tests for the git module, including tests for both synchronous and asynchronous execution of the methods
- Re-generated some of the documentation
- Possibly other small changes
Author: Chris (Someguy123) Date: Sat Dec 7 00:06:30 2019 +0000
-
Added
call_sys
function inhelpers.common
, an easier way to run and interact with external programs -
Added
shell_quote
function - small shim for python 3.8'sshlex.join
for backwards compatibility -
Added
call_sys_async
function inhelpers.asyncx
, which is a fully async version ofcall_sys
-
Added tests for
call_sys
andcall_sys_async
-
Improvements to
local_tests.sh
-
Re-factored most of
local_tests.sh
intolib/lib_test.sh
. lib_test.sh contains only shell functions, so it can be sourced into a bash shell for debugging local_tests.sh -
Now has a
QUIET
option, for less verbose output -
Re-factored virtualenv creation, detection and activation into
pyactivate
,venv_status
,is_current_venv
and others -
Handle script running from within an existing virtualenv cleanly.
-
Main body of the venv creation / test running has been moved into
main_tests()
in lib_test -
Now shows a summary at the end of the tests, so you can see which python versions caused tests to throw warnings and/or were skipped
-
Lots of other small improvements
-
-
Added gitignore lines for
dev_*.py
, sqlite databases, and adjustedvenv
lines to only affect root folder.
Author: Chris (Someguy123) Date: Thu Dec 5 02:53:08 2019 +0000
- Includes commit 12da829ff8da8b64549208ac92bb48c62f0af60c which enables 2.5.0 to function fully on Python 3.6 and 3.7 (prior to this commit some tests only worked on 3.8+)
commit 12da829ff8da8b64549208ac92bb48c62f0af60c
Date: Thu Dec 5 02:39:32 2019 +0000
Add local_tests.sh, fix get_function_params on older python
- Added `local_tests.sh` for running the unit tests on multiple python versions locally
- Added `OrderedDictObject` to collections module, since python versions before 3.8 cannot reverse a normal dict.
- Add unit tests for ordered dict object
- Adjusted `get_function_params` to use the new OrderedDictObject (fixes failing tests on older python versions)
New Features / Additions
-
privex.helpers.common
-
Added
get_function_params
- which extracts and filters a function/method or class constructor's parameters, and outputs them in a dictionary -
Added
construct_dict
, which allows you to either construct a class, or call a function using a dictionary of keyword arguments, usingget_function_params
to detect what arguments the class/function/method can take, including any parent classes, then filtering out any keyword arguments which would otherwise be rejected and cause a TypeError. -
Added
_filter_params
, a private function used by the aforementioned functions to filter a dictionary or iterable of Parameter objects.
-
-
New module
converters
, containing functions/classes designed to convert/parse one type into another-
convert_datetime
converts both string date/time's as well as unix timestamps intodatetime.datetime
objects usingdateutil.parser
-
convert_unixtime_datetime
converts specifically UNIX epoch timestamps (can be string, int, float, Decimal etc.) intodatetime.datetime
objects, and is used byconvert_datetime
to handle unix timestamps. -
convert_bool_int
converts booleansTrue
/False
as well as string / int versions into integers 1 (true) and 0 (false) -
convert_int_bool
is mostly an alias tois_true
, but exists for convenience and semantics (if there's a convert_bool_int, why not a convert_int_bool?)
Changes / Updates
-
Shrank the rather large copyright notice in most modules down to the small copyright block, and instead of dumping the whole X11 / MIT License text in there, the licence block simply states
License: X11 / MIT
. This should make the docs a bit more readable. -
Added
python-dateutil
to thePipfile
-
For sanity reasons,
python-dateutil
has been added to theinstall_requires
(meaning it's auto-installed when you install privex-helpers). The package is relatively small and depends on justsix
, weighing in around 500kb (python-dateutil = 468kb, six = 36kb).It may be removed and refactored into a setup.py extra at a later point, but for now it's small and commonly required enough that it can be a dependency.
-
Added
dateutil
to the sphinx intersphinx mapping -
Possibly other small changes I forgot to include
Testing
-
Added new test case
TestInspectFunctions
to test_general, which tests the newget_function_params
andconstruct_dict
functions. -
Added new test module
test_converters.py
which contains test cases for the new converters module-
TestConvertDate
covers date/time related converters such asconvert_datetime
andconvert_unixtime_datetime
-
TestConvertGeneral
covers other converters that don't fit into a specific category (or would otherwise be pointless to categorize)
-
-