brocksam / pyproprop Goto Github PK
View Code? Open in Web Editor NEWWrite classes with lots of similar simple defensive properties without the boilerplate
License: MIT License
Write classes with lots of similar simple defensive properties without the boilerplate
License: MIT License
An example error message should read:
Minimum number of collocation points per mesh section (`collocation_points_min`) must be greater than or equal to `2`. `0` is invalid.
Hyperlinks in install section of README do not render correctly as they've been incorrectly formatted using markdown syntax and not ReST syntax. The hyperlink to the installation page of the pyproprop readthedocs documentation also links to an error as the page does not exist.
Support formatting of strings to other cases such as camel and snake as well as upper, lower and title. This will mainly involve handling replacement of spaces and dealing with invalid characters. Upper cases used in abbreviations/acronyms will also need to be handled intelligently.
Examples:
some_string = "Some String with ABRV."
format_snake(some_string)
> "some_string_with_abrv"
format_camel(some_string)
> "SomeStringWithABRV"
Titlecase (https://github.com/ppannuto/python-titlecase) is not available on conda-forge.
It would be great to have the ability to directly access pyproprop
's string formatting functionality through a stand-alone function as well as through processed properties (as is currently implemented). The desired use case is outlined below:
from pyproprop import format_case
my_string = "this IS some-string__that I have etc."
print(format_case(mystring, case="hyphen"))
>>> "this-is-some-string-that-i-have-etc"
Package is now available on conda-forge so add badge and installation instruction for conda to README.rst.
Problem caused when trying to cast objects to Numpy ndarray
s caused by the fact that the type name is ndarray
while the constructor method is typically np.array
.
To be confirmed...
For example:
>>> format_str_start_case("a string")
"A string"
When calling a processed property with a post method, for example:
squares = processed_property(
"squares",
type=int,
iterable_allowed=True,
method=square()
)
The following is raised: NameError: name 'optional' is not defined
.
This is comping from line processed_property
line 537:
pyproprop/pyproprop/processed_property.py
Lines 524 to 539 in 693950b
Optional is not is in the scope of apply_method
.
Relavent to how #11 can be addressed.
When an error message is formatted for a list of options it should appear like:
>>> options = (None, "none", 3, "3")
>>> error_message(options)
Choose one of: 'None', '"none"', '3' or '"3"'.
Code safety may be improved if used of exec()
and locals()
is avoided. See:
pyproprop/pyproprop/processed_property.py
Lines 136 to 165 in 8aeb8cc
Processed properties allow the specification of a group of options that a user can then choose from. If an option from this group is chosen then an error is raised. Processed property options also allow for a default option to be
specified as well as for options to be specified as unsupported. Additionally dispatchers can be built using these options so that a specific function or class handle can be linked to the option identifiers. This module implements a framework to provide all of these things in a clean and easy-to-use way that is designed with use alongside processed properties in mind.
To do this currently is something like:
from pyproprop import processed_property
KEYWORD_IDENTIFIER_1 = "keyword_1"
KEYWORD_IDENTIFIER_2 = "keyword_2"
KEYWORD_IDENTIFIER_3 = "keyword_3"
OPTIONS = (KEYWORD_IDENTIFIER_1, KEYWORD_IDENTIFIER_2, KEYWORD_IDENTIFIER_3)
DEFAULT_OPTION = KEYWORD_IDENTIFIER_1
UNSUPPORTED_OPTIONS = KEYWORD_IDENTIFIER_3
class MyClassWithOptionsProperty:
my_property = processed_property(
"my_property",
type=str,
options=OPTIONS,
default=KEYWORD_IDENTIFIER_1
unsupported_options=KEYWORD_IDENTIFIER_3,
)
def __init__(self, my_property):
self.my_property = my_property
def my_dispatcher(self):
return {
KEYWORD_IDENTIFIER_1: SomeClass1,
KEYWORD_IDENTIFIER_2: SomeClass2,
KEYWORD_IDENTIFIER_3: SomeClass3,
}
Ideally this would be done something like:
from pyproprop import Options, processed_property
my_options = Options(
["keyword_1", "keyword_2", "keyword_3"],
unsupported=2,
callables=[SomeClass1, SomeClass2, SomeClass3]
)
class MyClassWithOptionsProperty:
my_property = processed_property(
"my_property",
type=str,
options=OPTIONS,
)
def __init__(self, my_property):
self.my_property = my_property
Coverage badge (using Coveralls http://coveralls.io) should be added to the README.rst.
pyproprop/pyproprop/processed_property.py
Line 126 in a21d412
some_property = processed_property("some_property", type=SomeType, optional=True, default=some_type_instance)
In the above use case, when some_property
is set to None
, pyproprop attempts to cast some_type_instance
to SomeType
and return the result (see referenced line in processed_property.py)
. If SomeType
is not 'castable' this raises an error.
Might it be more intuitive to simply return the user-supplied default value in this use case?
Setter method currently includes a number of chained if statements that must be traversed every single time the setter of a property is entered, even if the relevant keywords were ignored when instantiating the processed property. A dispatcher could be created when the processed property is instantiated that only dispatches calls to the required methods in the setter improving performance.
Example would be:
from pyproprop import processed_property
class SomeClass:
some_property_min = processed_property(
"some_property_min",
description="some property's minimum bounded value",
less_than="some_property_max",
)
some_property_max = processed_property(
"some_property_max",
description="some property's maximum bounded value",
less_than="some_property_min",
)
Uses new keyword:
less_than
greater_than
at_least
at_most
equals
Objects created that have an obvious (and valid) named that can be used as an identifier should be instantiated as collections.namedtuple
s so that they can be indexed using dot-indexing. Example:
obj_x = Obj(name="x")
obj_y = Obj(name="y")
obj_z = Obj(name="z")
some_iterable = [obj_x, obj_y, obj_z]
some_attribute = named_iterable(some_iterable)
assert some_attribute[0] is some_attribute.x is obj_x
assert some_attribute[1] is some_attribute.y is obj_y
assert some_attribute[2] is some_attribute.z is obj_z
I would like to be able to format a string before checking if it is one of a set of options:
prop = processed_property(
"prop_name",
str_format="hyphen",
options=OPTIONS_DISPATCHER.keys(),
)
This would involve simply reordering conditionals in the processed property setter method so that the string formatting comes before option checking.
I am happy to implement, but first want to check this potential refactor is compatible with other pyproprop
use cases?
Pytest-cases enables parametrisation of text fixtures and would allow (currently hardcoded) string formatting examples to be refactored into fixtures and used across multiple tests. Pytest-cases is presently not available on conda-forge, however this has been raised with maintainers: smarie/python-pytest-cases#135.
If pytest-cases is added to conda-forge the refactored tests are implemented in the repo at commit 3672345.
Use pyproprop version 0.4.3 or 0.4.2
For example see the following script:
from pyproprop import processed_property
class ExampleClass:
error_float = processed_property(
"error_float",
type=float,
iterable_allowed=True,
)
def __init__(self,
error_float):
self.error_float = error_float
this_will_error = ExampleClass(5.1)
5.1 is a valid float, however when the script is run, the following error is raised:
Traceback (most recent call last):
File "/Users/.../pyproproperror.py", line 15, in <module>
this_will_error = ExampleClass(5.1)
File "/Users/.../pyproproperror.py", line 13, in __init__
self.error_float = error_float
File "/Users/.../site-packages/pyproprop/processed_property.py", line 228, in prop
value = method(value, *args, **kwargs)
File "/Users/.../site-packages/pyproprop/processed_property.py", line 260, in check_expected_type
value = check_type(value, expected_type, name_str, optional,
File "/Users/.../site-packages/pyproprop/processed_property.py", line 299, in check_type
raise TypeError(msg)
TypeError: `error_float` must be a <class 'float'>, instead got a <class 'tuple'>.
Process finished with exit code 1
Now running the same script again, but with iterable_allowed=False, the script runs without issue.
Traceback (most recent call last):
File "match_sprint_sim.py", line 26, in <module>
standing_lap_forward_simulation = standing_lap_event.initialise_forward_simulation()
File "/home/peter/live/lapysim/lapysim/event.py", line 594, in initialise_forward_simulation
return self.event_phases[0]._initialise_event_phase_forward_simulation()
File "/home/peter/live/lapysim/lapysim/event.py", line 232, in _initialise_event_phase_forward_simulation
self._initialise_athletes()
File "/home/peter/live/lapysim/lapysim/event.py", line 248, in _initialise_athletes
athlete._initialise_dynamics(self)
File "/home/peter/live/lapysim/lapysim/athlete.py", line 503, in _initialise_dynamics
rolling_resistance_model = event.settings._instantiate_rolling_model(self.dynamics)
File "/home/peter/live/lapysim/lapysim/settings.py", line 54, in _instantiate_rolling_model
dynamics_model.associated_rr_model = self.rolling_resistance_model
File "/home/peter/anaconda3/envs/lapysim/lib/python3.7/site-packages/pyproprop/processed_property.py", line 85, in prop
check_options(value)
File "/home/peter/anaconda3/envs/lapysim/lib/python3.7/site-packages/pyproprop/processed_property.py", line 196, in check_options
with_preposition=True)
File "/home/peter/anaconda3/envs/lapysim/lib/python3.7/site-packages/pyproprop/processed_property.py", line 437, in format_for_output
return format_multiple_items_for_output(items, *args, **kwargs)
File "/home/peter/anaconda3/envs/lapysim/lib/python3.7/site-packages/pyproprop/processed_property.py", line 469, in format_multiple_items_for_output
first_word, _ = formatted_items.split(maxsplit=1)
ValueError: not enough values to unpack (expected 2, got 1)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.